How to initialize a generic property with child class of generic type?

Viewed 1975

I want to fill a generic property with one of the child classes. But I get this error:

Cannot implicitly convert type 'Child1' to 'T'

How can I do it?

For example:

Consider these parent and child classes:

public abstract class Parent
{
    public int P1 { get; set; }

    public abstract int DoSomething();
}
public class Child1 : Parent
{
    public override int DoSomething() { return P1 * 2; }
}
public class Child2 : Parent
{
    public override int DoSomething() { return P1 * 3; }
}

And also consider this sample generic class:

public class Sample<T> where T: Parent
{
    T ChildObject { get; set; }

    public int Test()
    {
        ChildObject = new Child1 { P1 = 2 }; // Error: Cannot implicitly convert type 'Child1' to 'T'

        return ChildObject.DoSomething();
    }
}

More explanation:

My mistake was I was trying to initialize child class in the generic class. Following the accepted answer, I should just add new constraint and do ChildObject = new T { P1 = 2 }; and then use ChildObject.DoSomething();.


Solution:

public class Sample<T> where T: Parent, new()
{
    T ChildObject { get; set; }

    public int Test()
    {
        ChildObject = new T { P1 = 2 }; // Fixed :)

        return ChildObject.DoSomething();
    }
}
2 Answers

Change your Sample class to:

public class Sample<T> where T : Parent, new()
{
    T ChildObject { set; get; }
    public Sample()
    {
        ChildObject = new T(); 
    }
}

you can now create an instance as:

var sample = new Sample<Child2>();

In order for this to work, Child1 and Child2 need to have a public parameterless constructor. This is documented here

Here is a more illustrative example:

class Tiger : Mammal {}
class Zebra : Mammal {}

public class Sample<TAnimal> where TAnimal: Mammal
{
    TAnimal ChildObject { set; get; }
    void Test()
    {
        ChildObject = new Tiger(); // Error: Cannot implicitly convert type 'Tiger' to 'TAnimal'
    }
}

Let's say we used Zebra for TAnimal. It will give us:

public class Sample<Zebra> where Zebra: Mammal
{
    Zebra ChildObject { set; get; }
    void Test()
    {
        ChildObject = new Tiger(); // Bang!
    }
}

Both Zebra and Tiger are mammals but it doesn't mean that Zebra is Tiger hence the error.

Related