猿问

有效地从 List<T> 返回 IList<Interface>

我有以下代码:


public interface ISomeObject

{

     IList<ISomeObject> Objects { get; }

}

public class SomeObject : ISomeObject

{

    public SomeObject()

    {

        Objects = new List<SomeObject>();

    }

    public List<SomeObject> Objects

    {

         get;

         set;

    }

    IList<ISomeObject> ISomeObject.Objects

    {    

        get 

        {

            // What to do here?

            // return Objects; // This doesn't work

            return Objects.Cast<ISomeObject>().ToList(); // Works, but creates a copy each time.

         }

    }

SomeObject有一个Objects返回类类型列表的公共属性。知道该类类型的客户可以使用它来做任何他们想做的事情。仅知道有关的客户只能ISomeObject使用该Objects属性来获取IList<ISomeObject>. 因为不允许转换List<SomeObject>为IList<ISomeObject>(由于苹果和香蕉问题),所以我需要一种转换方法。默认方式,使用 Cast.ToList() 工作,但有一个缺点,它每次评估属性时都会创建一个新列表,这可能很昂贵。更改ISomeObject.Objects为返回 anIEnumerable<ISomeObject>的另一个缺点是客户端不能再使用索引(这在我的用例中非常相关)。并且当在 IEnumerable 上使用时,重复使用 Linq 的 ElementAt() 调用是很昂贵的。


有没有人知道如何避免这两个问题?(当然,SomeObject到处宣传不是一种选择)。


四季花海
浏览 194回答 3
3回答

九州编程

更改ISomeObject.Objects为返回 anIEnumerable<ISomeObject>的另一个缺点是客户端不能再使用索引(这在我的用例中非常相关)。索引不仅受IList<T>接口支持,还受IReadOnlyList<T>接口支持。因为IReadOnlyList<T>不允许修改,所以它可以(并且是)协变,就像现在一样IEnumerable<T>。因此,只需将返回类型更改为IReadOnlyList<ISomeObject>并返回原始列表。当然,没有什么可以阻止调用者将结果转换为List<SomeObject>,但是调用者应该拥有对该列表的完全访问权限,因此不存在安全风险。

ibeautiful

您可能想尝试封装您List<SomeObject>的实现细节并返回IReadOnlyList<SomeObject>。然后SomeObject,ISomeObject由于IReadOnlyList变化,在接口实现中也不需要强制转换 want&nbsp;- 你将能够返回你的Objectsas&nbsp;IReadOnlyList<ISomeObject>。然后只需添加一些操作来改变您的基础列表,如Add或Remove容器类型(如果需要)。我还要提到的接口不是那么好了限制-邪恶的消费者可以轻松地投你ISomeObject要SomeObject和他做想要的一切,或许,你应该重新考虑你的设计。你最好坚持不变性和封装性这样的东西来提供可用的api。显式使用可变构建器,然后在合理的情况下用于不可变类。
随时随地看视频慕课网APP
我要回答