Parameter constraints without generics - c#

Given the following example...
public class Example
{
public static T GetDefaultValue<T>()
{
// return ???
}
}
Without using generics, what approach could I use to constrain the type passed in to the GetDefaultValue function to a class with a parameterless constructor that implements IDisposable?
How would I instantiate an instance of the that type to return from the GetDefaultValue function?

I'm confused by what you mean.. but instead of using generics (without generics?) you can constrain the type to an interface.
public ISomeInterface GetDefaultValue(ISomeInterface theObject)
{
...
}

With generics, you can do
public static T GetDefaultValue<T>() where T : new(), IDisposable
{
return new T();
}
Whatever type you set T to be must have a default constructor, though. This way, calling GetDefaultValue() will get you the precise type you need without the need to cast as you would have to if GetDefaultValue() returned an IDisposable.
I assume you didn't want a generics solution because the ability to instantiate a generic type is not well-known. I personally came across this by accident, and boy, is it a life saver!

Related

Create derived classes with parameterized constructors using factory method with type parameter

I have an abstract base class and a derived class. Let us call them Base and Derived.
Base has the constructor:
public Base(int number)
{
// do something with number
}
and the Derived class will always have the constructor (even though this cannot be ensured through an interface, this is nevertheless the case in my program):
public Derived(int number) : base(number)
{
// do some other stuff
}
Now, I would like a factory method to create objects derived from Base, which should be called like this:
Base.Create<Derived>(someNumber);
But I do not know how to implement this method in a correct fashion. I think the most elegant solution would be to do something like this:
public static T Create<T>(int number) where T : Base, new(int)
{
return new T(number);
}
But it seems that C# does not support the parameterized constructor constraint new(int), only the parameterless one. This solution would have been so clear and it expresses exactly what I want. Oh well..
Instead, I could basically switch on the type parameter and create and instance of the correct type like this:
public static Base Create<T>(int number) where T : Base, new(int)
{
if (typeof(T) == typeof(Derived))
{
return new Derived(number);
}
// and so on for all other derived types
}
But this requires me to update the method every single time I make a new derived class, which is unfortunate. Besides, typeof(T) == typeof(Derived) seems way too hackish. Also, with this approach it seems the return type of the factory method will have to be Base instead of T, which is also unfortunate. I could just as easily resort to using enums instead of a type parameter in that case.
I wonder if there is a better way to achieve what I want?
You can use an Activator to create an instance:
public static T Create<T>(int number) where T : Base
{
return (T) Activator.CreateInstance(typeof (T), number);
}
In this case you will not need to update the method if you create a new derived class. This assumes that you always have a constructor which takes a single integer parameter. If such constructor does not exist you will get a runtime exception.

Is it possible to constrain generic types to Interface, new()?

I'm trying to create a simple object recycling class
public class ObjectPool<T> where T : class, IRecyclable, new()
{
}
I want to be able to use it with my interface:
public interface ISomeInterface : IRecyclable
{
}
ObjectPool<ISomeInterface> pool = new ObjectPool<ISomeInterface>();
But this yields the error:
error CS0310: The type `ISomeInterface' must have a public parameterless constructor in order to use it as parameter `T' in the generic type or method `ObjectPool<T>'
From what I have read online I know that I can't specify a constructor in an interface.
I have read that you can use reflection instead of "new" to create a new instance, though I'm concerned about the speed of performing this instantiation.
What is the correct way to resolve this situation? Is there a simpler solution that I'm completely overlooking?
Interfaces can only implement other interfaces.
interface IA : IB, IC
{
...
}
A good way to solve your dilemma is to introduce a factory interface as well.
interface IThing
{
...
}
interface IThingFactory
{
IThing Create();
}
Now anything that wants to have the ability to create things should receive an IThingFactory for that purpose.
If you need a generic concept of a factory, you could use something like this:
interface IFactory<T>
{
T Create();
}
class ObjectPool<T, F>
where T : IRecyclable
where F : IFactory<T>
{
public ObjectPool(F factory)
{
...
}
}
You can't provide an interface there. class and new require it to be a constructable reference type.
You cannot construct an ObjectPool<ISomeInterface>. You could have a generic type MyClass<TT> where T:class,ISomeInterface,new() declare an ObjectPool<TT> within it, and then later on declare variables of type MyClass<SomeClassWhichImplementsISomeInterfaceAndHasADefaultConstructor>, but the compiler can only execute methods for ObjectPool<T> when T is of a particular known class type which meets all the constraints.
Alternatively, you could omit the new constraint and then require that any code which constructs an ObjectPool<T> must pass the constructor (or other method that creates the instance) a Func<T>. That would make it possible to create an ObjectPool<ISomeInterface> provided that one had a method which, when called, would return a new object of some suitable type that implemented ISomeInterface.

Getting the type for a "recursive generic"?

I do have a class, which is defined as:
public abstract class Singleton <T> : BaseObject
where T : Singleton <T>
{
}
I want to define an array of those generic singletons somewhere else. Something like
public MonoSingleton[] singletons;
How can I retrieve the proper type of that generic (that seems to be recursive, as you may see)? How can I write this out?
Are you trying to do the 'curiously recursive template pattern', like this?
class CuriouslyRecursiveBase<T>
{
}
class CuriouslyRecursiveDervied<T> : CuriouslyRecursiveBase<T>
{
}
class MyClass : CuriouslyRecursiveBase<MyClass>
{
}
To instantiate the derived from the base, you just use:
class CuriouslyRecursiveBase<T>
{
public static void InstantiateDerived()
{
T instance = (T)Activator.CreateInstance(typeof(T));
}
}
Since T is actually the derived type (MyClass) and curiously is also type (CuriouslyRecursive<MyClass>).
Specifically applied to your problem:
// Create a common interface that all singletons use. This allows
// us to add them all to a list.
interface ISingleton { }
class Singleton<T> : ISingleton
{
// Store our list of ISingletons
static List<ISingleton> instances = new List<ISingleton>();
static T instance;
protected Singleton() { }
public static T GetInstance()
{
// Either return the existing instnace, or create a new one
if (Singleton<T>.instance == null)
{
Singleton<T>.instance = (T)Activator.CreateInstance(typeof(T));
// Use a common interface so they can all be stored together.
// Avoids the previously mentioned co-variance problem.
// Also, compiler isn't built to follow curious recursiveness,
// so use a dynamic statement to force runtime re-evaluation of
// the type hierarchy. Try to avoid dynamic statements in general
// but in this case its useful.
instances.Add((dynamic)Singleton<T>.instance);
}
return Singleton<T>.instance;
}
}
class MyClass : Singleton<MyClass>
{
}
public static void Main()
{
MyClass my = MyClass.GetInstance();
}
More info:
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Using design-time code, you'll be able to get the type by using the typeof operator and giving some argument to the generic parameter:
typeof(Singleton<SomeImplementationOfBaseObject>)
Or
typeof(Singleton<>)
But there's an alternative: reflection.
Type singletonType = Type.GetType("NamespaceA.NamespaceN.Singleton`1");
The 1 part is the number of generic parameters. If you've something like Class<T, S> it would be 2 and so on.
Note that using reflection you don't need to give the generic argument. You can get the type with the generic parameter anyway. In order to give the generic argument, you would do this:
Type genericType = singletonType.MakeGenericType(typeof(SomeImplementationOfBaseObject));
Or if you want to get it directly, you would do this:
Type singletonType = Type.GetType("NamespaceA.NamespaceN.Singleton`1[[NamespaceA.NamespaceN.SomeImplementationOfBaseObject]]");
The string inside [[ ]] its the full name for the type passed as generic argument. Note that if the generic type isn't the same assembly as the executing one, you'll need to provide an assembly qualified name (for example, "NamespaceA.MyClass, MyAssembly").
UPDATE
The OP said in some comment:
If I do use: public Singleton<BaseObject>[] singletons;, it warns me
with: 'error CS0309: The type BaseObject' must be convertible to
Singleton' in order to use it as parameter 'T' in the
generic type or method 'Singleton'
This is another problem: you can't do covariance in classes. For doing such thing, you'll need an interface like this:
public interface ISingleton<out TBaseObject> where TBaseObject : .........
And make the Singleton<T> class implement it.
Thus, you can create such array this way:
public ISingleton<BaseObject>[] singletons;
Covariance lets you upcast generic parameters and it's limited to interfaces and delegates.
Learn more here:
http://msdn.microsoft.com/en-us/library/ee207183.aspx

Return object as interface from generic method

I have one interface InterfaceBase and some interfaces derived from it Interface1, Interface2. Next I have classes that are implementing the InterfaceX interfaces, not the base one.
Now, i am beginner in generics and so many new approaches in this made great mess in my head :( . I want to create factory (static class) where I call something like
Interface1 concrete1 = Factory.Get<Interface1>();
Here is my (sample) implementation of factory, that does not work:
public static class Factory {
public static T Get<T>() where T: InterfaceBase{
Type type = typeof(T);
//return new Concrete1() as T; // type T cannot be used with the as
//return new Concrete1() as type; //type not found
//return new Concrete1(); // cannot implicitly convert
//return new Concrete1() as InterfaceBase; //cannot convert IBase to T
//return new Concrete1() as Interface1; //cannot convert Interface1 to T
}
}
What I want to achieve is hide the classes (they are webservice handlers) from the rest of the application to exchange them lightly. I wanted use the factory as the classes will be singletons and they will be stored in Dictionary inside the factory, so the factory can spread them across the application through this method, but as interfaces..
Maybe i am not using the constraints correctly
am I doing smthing wrong? is my approach bad? can be there something better, maybe the whole architecture shoul be reworked? diagram to show better the architecture. The factory is not in it
Methinks what you are looking for is a "Poor-Man Dependency Injection". I guess you should use a real IoC container for that, there are a lot of options (Unity, Castle Windsor, Ninject...).
But anyway, If you insist in doing it by yourself, go with what #Sergey Kudriavtsev is recomending. Just make sure that, for each interface, you return the proper concrete class. Something like this:
public interface InterfaceBase { }
public interface Interface1 : InterfaceBase { }
public interface InterfaceX : InterfaceBase { }
public class Concrete1 : Interface1 { }
public class ConcreteX : InterfaceX { }
public static class Factory
{
public static T Get<T>()
where T : InterfaceBase
{
if (typeof(Interface1).IsAssignableFrom(typeof(T)))
{
return (T)(InterfaceBase)new Concrete1();
}
// ...
else if (typeof(InterfaceX).IsAssignableFrom(typeof(T)))
{
return (T)(InterfaceBase)new ConcreteX();
}
throw new ArgumentException("Invalid type " + typeof(T).Name, "T"); // Avoids "not all code paths return a value".
}
}
And you call it by passing the interface reference to the factory:
var instance = factory.Get<Interface1>();
This should work:
return (T)(new Concrete1());
Also the code for calling factory method should be like this:
Interface1 concrete1 = Factory.Get<Interface1>();
To answer one part of your question:
return new Concrete1() as T; // type T cannot be used with the as
Type T cannot be used with as because T is not known to be a reference type. You can constrain the class to be a reference type with the where T : class [, ...] constraint. This will allow you to use the as operator, assuming, of course, that you don't need to be able to use this method with value types.
EDIT
Having said that, I prefer rsenna's answer. Since you know at compile time that the direct cast will work, it makes more sense to use a direct cast than as. I also agree with his recommendation that you investigate "real" IoC containers, but I would add that a strong understanding of generics will be very useful to you as you learn about them. Since you say that you are a beginner in generics, an exercise like this one is probably a good idea, because it will help you learn about generics, and give you a better appreciation for the value that IoC containers can add.
EDIT 2
I see another problem: You constrain T to be InterfaceBase, and then you cast Concrete1 to T. Concrete1 is not known to derive from T! Which is of course why you use the as cast. So the answer is, add the class constraint and you should be fine.
EDIT 3
As rsenna points out, you can also get a runtime type check with an upcast and downcast:
return (T)(object)new Concrete1();
or
return (T)(InterfaceBase)new Concrete1();
I wonder how this compares in terms of efficiency with
return new Concrete1() as T;
I'll check later today if I find some time to do so.
Doing something like this
public static class Factory {
public static T Get<T>() where T: InterfaceBase{
return (T) new Concrete1();
}
Cannot be typed safely. You cannot guarantee that the method will be invoked with T == Concrete1. T can be ANY subtype of InterfaceBase, Concrete1 is just one of those subtypes and not necessarily the same T, therefore the compiler won't allow you to cast to T, the same way it won't allow you to cast to string or any other unrelated type.
Activator.CreateInstance() is one way of handling that: CreateInstance does guarantee that the built instance is of type T, which is the expected output value of the method.
If you know that T is a subtype of InterfaceBase (where T : InterfaceBase) then you can make the return type of the Get method be InterfaceBase:
public static InterfaceBase Get<T>() where T : InterfaceBase
{
return new Concrete1();
}
This method can be invoked using a sub-interface of InterfaceBase as T:
InterfaceBase ib = Factory.Get<Interface1>();
If you pass anything but a sub-interface of InterfaceBase as T the compiler will complain.
I think this is a better approach but as #phoog points it only works with concrete classes for the T type parameter:
public static T Get<T>() where T : InterfaceBase
{
Type type = typeof(T);
if (t.IsAbstract || t.IsInterface)
{
throw new ArgumentException(#"Only non-abstract classes supported as T type parameter.");
}
return Activator.CreateInstance<T>();
}

C# generic factory method

Perhaps this is a simple newbie C# question, but so be it---it will be a fresh break from my other questions, which are so difficult that no one knows the answer to them. :)
Let's say I have a generic type in C#:
Thing<T>
And let's say I want to make a thing using a static factory method. In Java, this is no problem:
public static <T> Thing<T> createThing()
{
return flag ? new Thing<Integer>(5) : new Thing<String>("hello");
}
How do I do this in C#? Thanks.
If you want to return an instance of a templated class using one of many different template arguments, one way to do it is with an abstract base (or an interface):
abstract class UntypedThing { }
class Thing<T> : UntypedThing
{
public Thing(T t) { }
}
class Foo
{
public static UntypedThing createThing(bool flag)
{
if (flag)
return new Thing<int>(5);
else return new Thing<String>("hello");
}
}
The UntypedThing class would contain as much code as possible that does not rely on the template type. The Thing class would ideally only contain code that relies on the template type. The factory class Foo always returns the former.
You can in theory use reflection to build up the correct generic type, but it will be pretty useless to you as at some point you will need to upcast it to a less specific type.
public class ThingFactory {
public object Create(bool flag) {
Type outputType = null;
if(flag) {
outputType = typeof(string);
} else {
outputType = typeof(int);
}
return Activator.CreateInstance(typeof(Thing<>).MakeGenericType(outputType));
}
}
As you can see, the value of doing this is about zero as you will need to cast the return type to the type you want, meaning that the logic to determine it needs to live outside the Create method.
I would use Reinderien's method and have a non-generic base. This is the most sane and idiomatic approach.
Oh, the trouble I get myself in when I simply try to do something simple.
It turns out that C# 4 allows this sort of covariance---sort of. First, I have to make Thing an interface and specify the "out" generic parameter:
public interface Thing<out T> {...}
But if I do certain things, C# won't let me use covariance. For example, if I try to return T from the interface:
public interface Thing<out T>
{
public T GetT();
Even if I manage to get covariance with Thing, what do I do with it?
Thing<object> thing=createThing();
The compiler tells me that the type cannot be inferred from usage.
Let's say I say screw the whole T thing and make the factory method return Thing of type object:
public static Thing<object> createThing() {...}
Fine, but now where do I put it?
IList<Thing<object>> list=new List<Thing<object>>();
Thing<object> thing=createThing();
list.Add(thing);
Yes, I have to say that this is a list of Thing with T of type Object, because C# has no wildcard type.
If this were Java, I'd simply say:
public class Thing<T> {...}
public static <T> Thing<T> createThing() {...}
List<?> things=new ArrayList<Thing<?>>();
Thing<?> thing=createThing();
things.add(thing);
If I wanted extra safety by saying that T had to be of a special type, I'd say:
public static <T extends MyBaseType> Thing<T> createThing() {...}
List<? extends MyBaseType> things=new ArrayList<Thing<? extends MyBaseType>>();
Thing<? extends MyBaseType> thing=createThing();
things.add(thing);
Then I'd figure out what T is later, when I had more information.
This all seems to come down to incomplete generic covariance in C# coupled with the lack of C# generic wildcards. (I still maintain it isn't an erasure issue.)
So what do I do? The only simple thing to do seems to follow Reinderien's answer and split out a non-generic base class.
(I wonder if in this non-generic base class I could have object getValue() and then use covariance in the subclass to return T getValue()? Ack, I'm tired of this---I'll leave that for another day.)

Categories

Resources