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

public interface IMyInterface
{
    void MyMethod();
}

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

public class MyContainer<T> where T : IMyInterface
{
    public IList<T> Contents;
}

然后,我可以执行此操作,效果很好:
MyContainer<MyClass> container = new MyContainer<MyClass>();
container.Contents.Add(new MyClass());

我有许多实现MyInterface的类。我想编写一个可以接受所有MyContainer对象的方法:
public void CallAllMethodsInContainer(MyContainer<IMyInterface> container)
{
    foreach (IMyInterface myClass in container.Contents)
    {
        myClass.MyMethod();
    }
}

现在,我想调用此方法。
MyContainer<MyClass> container = new MyContainer<MyClass>();
container.Contents.Add(new MyClass());
this.CallAllMethodsInContainer(container);

那没用。当然,因为MyClass实现了IMyInterface,所以我应该能够进行转换吗?
MyContainer<IMyInterface> newContainer = (MyContainer<IMyInterface>)container;

那也不起作用。我绝对可以将常规MyClass强制转换为IMyInterface:
MyClass newClass = new MyClass();
IMyInterface myInterface = (IMyInterface)newClass;

因此,至少我还没有完全误解这一点。我不确定我该如何编写一种方法,该方法接受符契约(Contract)一接口(interface)的类的泛型集合。

我有计划在需要时完全解决此问题,但我真的更愿意正确地解决。

先感谢您。

最佳答案

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

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

public IList<T> Contents = new List<T>();

如果不这样做,则可以执行以下操作:
public IList<MyInterface> Contents = new List<MyInterface>();

方法1:

将方法更改为:
public void CallAllMethodsInContainer<T>(MyContainer<T> container) where T : IMyInterface
{
    foreach (T myClass in container.Contents)
    {
        myClass.MyMethod();
    }
}

和摘要到:
MyContainer<MyClass> container = new MyContainer<MyClass>();
container.Contents.Add(new MyClass());
this.CallAllMethodsInContainer(container);

方法2:

或者,将CallAllMethodsInContainer方法移动到MyContainer<T>类,如下所示:
public void CallAllMyMethodsInContents()
    {
        foreach (T myClass in Contents)
        {
            myClass.MyMethod();
        }
    }

并将代码段更改为:
MyContainer<MyClass> container = new MyContainer<MyClass>();
container.Contents.Add(new MyClass());
container.CallAllMyMethodsInContents();

方法3:

编辑:另一个替代方法是从MyContainer类中删除通用约束,如下所示:
public class MyContainer
{
    public IList<MyInterface> Contents;
}

并将方法签名更改为
  public void CallAllMethodsInContainer(MyContainer container)

然后,该代码段应按以下方式工作:
MyContainer container = new MyContainer();
container.Contents.Add(new MyClass());
this.CallAllMethodsInContainer(container);

请注意,使用此替代方法,容器的Contents列表将接受实现MyInterface的对象的任何组合。

10-07 21:02
查看更多