I found two ways to workaround the lack of 'new(parameters)' in generics but I'm wondering if there's a better solution for that situation.
I require a method in Earth that creates any Fruit using the Dna as parameter in ctor. I have lots of fruits.
Using Activator (or any similar form) has the disadvantage that breaks if the derived class has not the corret ctor or are abstract.
public class Earth
{
public Earth()
{
var dna = new Dna();
var orange = GetFruit<Orange>(dna);
}
private static T GetFruit<T>(Dna dna) where T : Fruit
{
return (T)Activator.CreateInstance(typeof(T), dna);
}
}
public abstract class Fruit
{
public Fruit(Dna dna)
{
}
}
public class Orange : Fruit
{
public Orange(Dna dna)
: base(dna)
{
}
}
public class Dna
{
}
Using a parameterless ctor has the disadvantage that the mandatory Dna becomes optional. The same for a 'Initialize(Dna dna)' method.
public class Earth
{
public Earth()
{
var dna = new Dna();
var orange = GetFruit<Orange>(dna);
}
private static T GetFruit<T>(Dna dna) where T : Fruit, new()
{
return new T() { Dna = dna };
}
}
public abstract class Fruit
{
public Dna Dna { get; set; }
}
public class Orange : Fruit
{
}
public class Dna
{
}
One option is to add another parameter: a Func<Dna, T>
:
private static T GetFruit<T>(Dna dna, Func<Dna, T> ctor) where T : Fruit
{
// I assume your real code does more here?
return ctor(dna);
}
Then you can use:
var orange = GetFruit(dna, x => new Orange(x));
Note that that also means you don't need to specify the type argument explicitly. The downside is that if you're going to call this from another generic method, you'd need to pass the construction delegate throughout the stack :(
See more on this question at Stackoverflow