【问题标题】:How to pass List of class to List of Interface?如何将类列表传递给接口列表?
【发布时间】:2011-11-29 15:23:58
【问题描述】:

我有这样的功能:

DoSomething(List<IMyInterface>)

IMyInterface 是一个接口,而 MyClass 是一个实现该接口的类 类 MyClass:IMyInterface

我打电话给DoSomething(List&lt;MyClass&gt;),它看起来不起作用。 如何将类的列表作为函数的参数传递给类的接口列表?谢谢!

【问题讨论】:

    标签: c# class list interface


    【解决方案1】:

    如果您的代码只是简单地迭代方法内的序列(而不是添加、删除或按索引访问),请将您的方法更改为以下之一

    DoSomething(IEnumerable<IMyInterface> sequence)
    DoSomething<T>(IEnumerable<T> sequence) where T : IMyInterface
    

    IEnumerable&lt;&gt; 接口是协变的(从 .NET 4 开始)(第一个选项)。或者,如果使用 C# 3,您可以使用后一个签名。

    否则,如果您需要索引操作,请在传递之前转换列表。在调用中,您可能有

    // invocation using existing method signature 
    DoSomething(yourList.Cast<IMyInterface>().ToList());
    
    // or updating method signature to make it generic
    DoSomething<T>(IList<T> list) where T : IMyInterface
    

    后一个签名允许您做的是还支持添加或删除列表(在调用站点可见),它还允许您使用列表而无需先复制它。

    即便如此,如果您所做的只是在循环中遍历列表,我更倾向于接受IEnumerable&lt;&gt; 的方法。

    【讨论】:

    • 对于索引操作和删除,DoSomething&lt;T&gt;(IList&lt;T&gt; list) where T : IMyInterface 不也可以工作吗? (无需复制列表。)
    • @Sli,是的,他可以使方法通用。我已更新以显示通用选项。
    • 另一种方法是定义一个接口 IReadableList,然后编写一个实现该接口和 IList 的包装类。不过,不幸的是,必须更改其他代码才能使用包装类。可以定义从 List 到 ListWrapper 的扩大转换,但这会有点麻烦,而且它无助于系统识别 List 可以变成某种东西(ListWrapper) 实现 IReadableList.
    【解决方案2】:

    这通常是不安全的,因为列表是可变的。假设您将List&lt;MyClass&gt; 的引用传递给某人作为List&lt;IMyInterface&gt;,那么他们会这样做:

    void Foo(List<IMyInterface> list)
    {
        IMyInterface x = new MyOtherClassWhichAlsoImplementsIMyInterface();
        list.Add(x);
    }
    

    现在您的List&lt;MyClass&gt; 包含一个不是MyClass 的类的实例。这将违反类型安全。 (正如其他答案所述,您可以通过仅传递 List 的 IEnumerable&lt;&gt; 接口来避免此问题,该接口提供只读访问,因此是安全的。

    更多详情,请参阅Using Variance in Interfaces for Generic Collections on MSDN。另见a good summary of covariance and contravariance and various C# features that support it

    【讨论】:

      【解决方案3】:

      如果您只需要遍历列表,请使用 IEnumerable 声明方法。如果您想向列表中添加元素,您所要求的不是类型安全的,因此在 C# 中可能不允许。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-30
        • 1970-01-01
        相关资源
        最近更新 更多