在c#中使用泛型时请帮助我理解多态性

Ste*_*uts 9 c# asp.net generics nested-generics asp.net-mvc-2

我在使用泛型时理解多态如何工作时遇到了问题.举个例子,我定义了以下程序:

public interface IMyInterface
{
    void MyMethod();
}

public class MyClass : IMyInterface
{
    public void MyMethod()
    {
    }
}

public class MyContainer<T> where T : IMyInterface
{
    public IList<T> Contents;
}
Run Code Online (Sandbox Code Playgroud)

我可以这样做,这很好用:

MyContainer<MyClass> container = new MyContainer<MyClass>();
container.Contents.Add(new MyClass());
Run Code Online (Sandbox Code Playgroud)

我有很多实现MyInterface的类.我想编写一个可以接受所有MyContainer对象的方法:

public void CallAllMethodsInContainer(MyContainer<IMyInterface> container)
{
    foreach (IMyInterface myClass in container.Contents)
    {
        myClass.MyMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我想称之为这种方法.

MyContainer<MyClass> container = new MyContainer<MyClass>();
container.Contents.Add(new MyClass());
this.CallAllMethodsInContainer(container);
Run Code Online (Sandbox Code Playgroud)

那没用.当然,因为MyClass实现了IMyInterface,我应该能够实现它吗?

MyContainer<IMyInterface> newContainer = (MyContainer<IMyInterface>)container;
Run Code Online (Sandbox Code Playgroud)

那也行不通.我绝对可以将一个普通的MyClass转换为IMyInterface:

MyClass newClass = new MyClass();
IMyInterface myInterface = (IMyInterface)newClass;
Run Code Online (Sandbox Code Playgroud)

所以,至少我没有完全误解这一点.我不确定我是如何编写一个接受符合相同接口的类的泛型集合的方法.

如果需要的话,我有计划彻底解决这个问题,但我真的更愿意这样做.

先感谢您.

Ani*_*Ani 4

注意:在所有情况下,您都必须将该Contents字段初始化为实现IList<?>

当您保留通用约束时,您可以执行以下操作:

public IList<T> Contents = new List<T>();
Run Code Online (Sandbox Code Playgroud)

当你不这样做时,你可以这样做:

public IList<MyInterface> Contents = new List<MyInterface>();
Run Code Online (Sandbox Code Playgroud)

方法一:

将方法更改为:

public void CallAllMethodsInContainer<T>(MyContainer<T> container) where T : IMyInterface
{
    foreach (T myClass in container.Contents)
    {
        myClass.MyMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

和片段:

MyContainer<MyClass> container = new MyContainer<MyClass>();
container.Contents.Add(new MyClass());
this.CallAllMethodsInContainer(container);
Run Code Online (Sandbox Code Playgroud)

方法二:

或者,将该CallAllMethodsInContainer方法移至类中MyContainer<T>,如下所示:

public void CallAllMyMethodsInContents()
    {
        foreach (T myClass in Contents)
        {
            myClass.MyMethod();
        }
    }
Run Code Online (Sandbox Code Playgroud)

并将代码片段更改为:

MyContainer<MyClass> container = new MyContainer<MyClass>();
container.Contents.Add(new MyClass());
container.CallAllMyMethodsInContents();
Run Code Online (Sandbox Code Playgroud)

方法三:

编辑:另一种选择是从类中删除通用约束,MyContainer如下所示:

public class MyContainer
{
    public IList<MyInterface> Contents;
}
Run Code Online (Sandbox Code Playgroud)

并将方法签名更改为

  public void CallAllMethodsInContainer(MyContainer container)
Run Code Online (Sandbox Code Playgroud)

那么该片段应该如下工作:

MyContainer container = new MyContainer();
container.Contents.Add(new MyClass());
this.CallAllMethodsInContainer(container);
Run Code Online (Sandbox Code Playgroud)

请注意,使用此替代方案,容器的Contents列表将接受实现MyInterface.