It doesn't work as the compiler can't check if T is always an int when using IntegerReturner etc. For example, the following call would be valid according to the method signature:
factory.CreateValueReturner<bool>("IntegerReturner")
where it would have to return an
IReturnsValue<int>
as an
IReturnsValue<bool>
.
You can "take over responsibility" and cast in the factory. So:
public IReturnsValue<T> CreateValueReturner<T>(string name)
{
if (name == "IntegerReturner")
return (IReturnsValue<T>)new IntegerReturner();
if (name == "DoubleReturner")
return (IReturnsValue<T>)new DoubleReturner();
throw new ArgumentException();
}
you will then get a runtime exception if the types do not match.
You also have to specify the type in the Main method as T isn't defined here (or use
var
of course):
IReturnsValue<int> firstValueReturner = factory.CreateValueReturner<int>("IntegerReturner");
IReturnsValue<double> secondValueReturner = factory.CreateValueReturner<double>("DoubleReturner");
It's hard to say if there are better ways to implement this, it depends on the rest of the code and personal preference. If it was me, I would consider if I could get rid of the name and select the class to instantiate from the type of T - then you can't have a situation where T and name do not match. The factory method can be something like this:
public IReturnsValue<T> CreateValueReturner<T>()
{
if (typeof(T) == typeof(int))
return (IReturnsValue<T>)new IntegerReturner();
if (typeof(T) == typeof(double))
return (IReturnsValue<T>)new DoubleReturner();
throw new ArgumentException();
}