Problem
Can I instantiate a piece of fruit in a generic method like this if BaseFruit includes a constructor that accepts an int weight?
public void AddFruit<T>()where T: BaseFruit{
BaseFruit fruit = new T(weight); /*new Apple(150);*/
fruit.Enlist(fruitManager);
}
Behind the comments, there is an example. It appears that the only way to accomplish this is to provide BaseFruit a parameterless constructor and then fill in the blanks using member variables. This is really impractical in my real code (not about fruit).
-Update- It appears that restrictions cannot be used to fix the problem in any way. There are three possible solutions based on the responses:
I believe reflection is the dirtiest, but I can’t decide between the other two.
Asked by Boris Callens
Solution #1
Also, here’s a simple example:
return (T)Activator.CreateInstance(typeof(T), new object[] { weight });
The new() constraint on T is just used to force the compiler to look for a public parameterless constructor at compilation time; the Activator class is the code that actually creates the type.
You’ll need to double-check that the specific constructor exists, and this type of requirement could be a code smell (or, at the very least, something you should aim to avoid in the current c# version).
Answered by meandmycode
Solution #2
There are no parameterized constructors available. If you have a “where T: new()” constraint, you can utilize a parameterless constructor.
It’s inconvenient, but that’s life:(
One of the issues I’d like to address with “static interfaces” is this one. Then you can confine T to just include static methods, operators, and constructors, and then call them.
Answered by Jon Skeet
Solution #3
Yes, modify your location:
where T:BaseFruit, new()
This, however, only works with constructors that have no parameters. You’ll need to find another way to establish your property (setting the property itself or something similar).
Answered by Adam Robinson
Solution #4
Activator is the most straightforward solution. CreateInstance()
Answered by user1471935
Solution #5
As Jon pointed out, restricting a non-parameterless constructor is a way of life. A manufacturing pattern, on the other hand, is a different solution. This is a simple constraint.
interface IFruitFactory<T> where T : BaseFruit {
T Create(int weight);
}
public void AddFruit<T>( IFruitFactory<T> factory ) where T: BaseFruit {
BaseFruit fruit = factory.Create(weight); /*new Apple(150);*/
fruit.Enlist(fruitManager);
}
A functional approach is still another alternative. A factory method can be passed in.
public void AddFruit<T>(Func<int,T> factoryDel) where T : BaseFruit {
BaseFruit fruit = factoryDel(weight); /* new Apple(150); */
fruit.Enlist(fruitManager);
}
Answered by JaredPar
Post is based on https://stackoverflow.com/questions/731452/create-instance-of-generic-type-whose-constructor-requires-a-parameter