C# generic factory method - c#

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.)

Related

generic methods: how to force using the most specialized method available

I defined a generic method Use<T> in an interface IInterface. I tried to make an implementation of that interface where the concrete implementation of the Use<T> method depends on the actual type T, and I want to always call the most specialized method. But it does not work:
interface IInterface { void Use<T>(T other) where T : IInterface; }
interface IChildInterface : IInterface { }
class ImplementsIInterface : IInterface
{
public void Use<T>(T other) where T : IInterface
{
Debug.WriteLine("ImplementsInterface.Use(IInterface)");
}
}
class ImplementsChildInterface : IChildInterface
{
public void Use<T>(IChildInterface other) where T : IInterface
{ // idea: if other is IChildInterface, use this method
Debug.WriteLine("ImplementsChildInterface.Use(IChildInterface)");
}
public void Use<T>(T other) where T : IInterface
{ // idea: if above method is not applicable, use this method
Debug.WriteLine("ImplementsChildInterface.Use(IInterface)");
}
}
Here is my main method:
public static void Main()
{
IChildInterface childinterf = new ImplementsChildInterface();
childinterf.Use(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
// but should output "ImplementsChildInterface.Use(IChildInterface)"
childinterf.Use(new ImplementsIInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
}
The method that takes an IChildInterface argument is never called, although it should.
Is there a way to make this work? Or is my approach fundamentally wrong?
Note that it is a necessity that IInterface only has one method definition. I might enlarge the interface hierarchy at any time (and thus increase the number of implementations I could provide in an implementing class), but this should not lead to needing to add more method definitions in IInterface. Otherwise, the whole point of using interfaces (i.e. to be flexible) would be missed.
The answers I got so far all involve the need to cast. This is also something I don't want to do, since it makes the whole setup useless. Let me explain the broader picture of what I try to achieve:
Let's imagine we created some instance of an IInterface (like so: IInterface foo = new ImplementsChildInterface();). It will behave in a certain way, but it will always behave in the same way - no matter if we see it as an IInterface, an IChildInterface or an ImplementsChildInterface. Because, if we call some method on it, the compiler (or runtime? i don't know) will check what type it REALLY is and run the method defined in that type.
Now imagine we have two instances i1 and i2 of IInterface. They again are, under the hood, concrete implementations of IInterface, so they have a concrete behaviour, no matter through which glasses we seem them.
So when I run i1.Use(i2), the compiler (or runtime?) should be able to find out what i1 and i2 REALLY are, and run the corresponding method. Like so:
Which type does i1 have? ImplementsChildInterface, ok, then I'll look at the methods there.
Which type does i2 have? ImplementsIInterface, ok, then let's see if there exists a method Use(ImplementsIInterface ...). There is none, but maybe there is a fallback? ImplementsIInterface is a IInterface, so let's see if there exists a method Use(IInterface ...). Yes, it exists, so let's call it!
Neither IInterface nor IChildInterface have a member Use<T>(IChildInterface other) defined, but only Use<T>(T other).
Your class ImplementsChildInterface on the other side has a method Use<T>(IChildInterface other). As you declaring childInterf as a reference of type IChildInterface you can´t access that member, but unly those defined in the interface. So you should cast to the actual class in order to access the method accepting an instance of IChildInterface. But even then the generic implementation is used. So you should also cast your parameter to IchildInterface:
ImplementsChildInterfacechildinterf = new ImplementsChildInterface();
childinterf.Use(((IChildInterface)new ImplementsChildInterface());
childinterf.Use(new ImplementsIInterface());
Furthermore as you don´t use the generic type-parameter within your more specialized method, you can also omit it:
class ImplementsChildInterface : IChildInterface
{
public void Use(IChildInterface other)
{ // idea: if other is IChildInterface, use this method
Debug.WriteLine("ImplementsChildInterface.Use(IChildInterface)");
}
public void Use<T>(T other) where T : IInterface
{ // idea: if above method is not applicable, use this method
Debug.WriteLine("ImplementsChildInterface.Use(IInterface)");
}
}
Alternativly you may also add a method into your IChildInterface:
void Use<T>(IChildInterface other) where T : IChildInterface;
Now you can use
IChildInterface childinterf = new ImplementsChildInterface();
childinterf.Use<IChildInterface>(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
which will print the desired output.

Parameter constraints without generics

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!

Is it a acceptable to hide a property in a derived interface which returns a derived type?

TL;DR
What is wrong with hiding a property in an interface so that I can change its declaration to return a derived type of the original property?
I'm sure this must have been asked before, but I can't find it, and apologies for the long question.
Say I have this situation:
public interface A
{
B TheB{get;}
}
public interface MoreSpecificA : A
{
MoreSpecificB TheMoreSpecificB{get;}
}
public interface B{...}
public interface MoreSpecificB:B{...}
I would like users of MoreSpecificA to be able to get at the B which is a MoreSpecificB. They could do this by calling TheB and cast it, or they could call the method TheMoreSpecificB. I could also declare MoreSpecificA like so:
public interface MoreSpecificA : A
{
new MoreSpecificB TheB{get;}
}
so that now they can just use the same method and get back a MoreSpecificB.
Using the new to hide a method puts my teeth on edge, so why is this a bad idea? It seems like a reasonable thing to do here.
The general suggestion in most cases I have seen for this seems to be to use generics instead, but this seems to have a problem in that if I have a MoreSpecificA and I want to return it in a method that declares the return type as A then I have to have MoreSpecificA extend A which gives ambiguity when accessing TheB on the MoreSpecificA instance as it doesn't know if you want A.TheB or MoreSpecificA.TheB
public interface ABase<T> where T : B
{
T TheB{get;}
}
public interface A : ABase<B>
{
}
public interface MoreSpecificA : ABase<MoreSpecificB>,A
{
}
public class blah
{
public A GetA(MoreSpecificA specificA)
{
return specificA; //can't do this unless MoreSpecificA extends A
}
public B GetB(MoreSpecificA specificA)
{
return specificA.TheB; //compiler complains about ambiguity here, if MoreSpcificA extends A
}
}
which could be solved by declaring a new TheB on MoreSpecificA (but the new issue again).
If MoreSpecificA doesn't extend A then the first method in the class blah above complains as now as MoreSpcificA can't be converted to A.
Whilst writing this I have noticed that if I declare my BaseA to be contravariant like this:
public interface ABase<out T> where T : B
{
T TheB{get;}
}
and my class to be
public class blah
{
public ABase<B> GetA(MoreSpecificA specificA)
{
return specificA;
}
public B GetB(MoreSpecificA specificA)
{
return specificA.TheB; //compiler complains about ambiguity here
}
}
Then I get the best of both worlds. Does the applicability of this solution depend on whether A adds anything to ABase?
Or is my original plan of just hiding the method in the derived type to return a derived type of the original method ok?
Or is my original plan of just hiding the method in the derived type to return a derived type of the original method ok?
So long as it means exactly the same thing, I think it's okay. You can see something like this in the standard libraries, with IDbConnection.CreateCommand (which returns IDbCommand) and SqlConnection.CreateCommand (which returns SqlCommand) for example.
In that case it's using explicit interface implementation for the IDbConnection version, but it's the same principle.
You can also see it in IEnumerator<T>.Current vs IEnumerator.Current and IEnumerable<T>.GetEnumerator() vs IEnumerable.GetEnumerator().
I would only use it in cases where the implementation for the more weakly-typed method just returns the result of calling the more strongly-typed method though, use implicit conversion. When they actually start doing different things, that becomes much harder to reason about later.

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>();
}

Is there a way to apply c# generic constraints severally rather than jointly?

Is there a way to apply several different csharp generic constraints to the same type where the test is OR rather than AND?
I have an extension method I want to apply to a subset of an interface, but there is no common interface or base class that only captures the classes I wish to target.
In the example below, I could write multiple methods each with a single constraint that all call the same Swim method, but I am wondering if there is a way to write one method with multiple non-intersecting constraints.
Eg
interface IAnimal
{
bool IsWet { get; set; }
bool IsDrowned { get; set; }
}
public static class SwimmingHelpers
{
/*this is the psuedo effect of what I would like to achieve*/
public static void Swim<T>(this T animalThatCanSwim)
where T: IAnimal, Human |
where T: IAnimal, Fish |
where T: IAnimal, Whale ....
}
FYI The actual scenario I am toying with is HTML elements that all implement an IElement interface but I want to target only elements where certain behaviours are valid in the HTML specification and no more specific common interface is implemented by them eg: elements that can have a readonly attribute.
Not with generics. You could, however, get what you want by defining plain overloads like this:
public static class SwimmingHelpers {
public static void Swim(this Human animalThatCanSwim) {
SwimInternal(animalThatCanSwim);
}
public static void Swim(this Fish animalThatCanSwim) {
SwimInternal(animalThatCanSwim);
}
public static void Swim(this Whale animalThatCanSwim) {
SwimInternal(animalThatCanSwim);
}
private static void SwimInternal(IAnimal animalThatCanSwim) {
// do your work here, no duplication of the code needed
}
}
The reason it doesn't work that way makes sense when you consider the fact that generic constraints aren't there to enforce your intended use of the method. Rather, they are there to allow you to make certain assumptions about the type parameter. For example, by constraining the type to be IComparable, you know that you can call a Compare method even though the exact type is not known yet. Constraining a type with new() ensures that you can call a default constructor on the type. So if generic constraints allowed you to specify one constraint or another, you could not make those assumptions.
There is no OR operator in generics.
But you can always introduce new interface to capture the subset of classes, ie. IReadOnly. This can be a marker interface that doesn't define any methods. Over time you might actually to find some usage for those new interfaces...

Categories

Resources