开发者

In c#, is there way to write a generic such that Object<Child> : Object<Parent>?

开发者 https://www.devze.com 2023-01-07 22:24 出处:网络
Is there a way to do something like this in c#? Consider the following example and assume that Child1, Child2, Child3 are all children of Parent -

Is there a way to do something like this in c#? Consider the following example and assume that Child1, Child2, Child3 are all children of Parent -

class Class1
{

  SomeObject< Parent > mSomeObject; 

  Class1()
  {

     if (condition1)

          mSomeObject = new SomeObject<Child1>();

     else if (condition2) 

          mSomeObject = new SomeObject<Child2>(); 

     else if (condition3) 

          mSomeObject = new SomeObject<Child3>();

  }

}

The idea is that that Class1 wou开发者_运维技巧ld have SomeObject as a member, but it is uncertain until runtime what generic form of SomeObject it should take. Any help would be appreciated. Thanks!


You should use interface based inheritance. This will allow child1, child2, and child3 to be polymorphic and take on the characteristics of the parent without the need for such guard logic. With the IF tests gone your code will be more readable and easier to modify later.

Here's and example I just wrote with LINQPad to show this in action.

public interface ICar
{
    bool IsAutomatic();
}

public class Silverado : ICar
{
    public bool IsAutomatic()
    {
        return true;
    }
}

public class Semi : ICar
{
    public bool IsAutomatic()
    {
        return false;
    }
}

void Main()
{
    ICar car = new Silverado();
    bool isAuto = car.IsAutomatic();
    isAuto.Dump();

    car = new Semi();
    isAuto = car.IsAutomatic();
    isAuto.Dump();
}

OUTPUT:

True
False

I prefer interface based inheritance as opposed to abstract classes as described by AllenG. Reasons such as multiple inheritance - a class can implement many interface but only inherit from 1 class.

Hope this helps...


You could do this. Notice the use of the out keyword here to make the type covariant.

public interface ISomeObject<out T>
{
}

However, this will somewhat restrict what you can do with T in the interface. Specifically you can only declare members where T is in the output position. In other words, it cannot be accepted as a parameter to a function.


I've never tried it, but I believe you are correct. In general if

public class Child : Parent

then any call for Parent will be satisfied by Child.

For instance:

public class Animal { //stuff }
public class Cat : Animal { // overridden stuff }

List<Animal> pets = new List<Animal>;
pets.Add(new Cat());

would work.

If you're looking for behavior, you may want to be working with Interfaces instead of class inheritance, but it would work the same way.

No, the problem you may have with your approach is that your SomeObject<Parent> will only have access to those members in your Parent class. To use anything in the appropriate Child class, you'll need to cast back to the appropriate Child.


You can do this in C# 4.0 with an interface or a delegate but not with a class. Consider changing the property to an interface type and read more about generics covariance and contravariance in C# 4.0 (for example here: http://msdn.microsoft.com/en-us/library/ee207183.aspx )

0

精彩评论

暂无评论...
验证码 换一张
取 消