IList<T>和IEnumerable<T>哪个更高效?

13

如何更有效地使方法返回 IList<T>IEnumerable<T>

IEnumerable<T> 是不可变集合,IList<T> 是可变集合,且包含许多有用的方法和属性。

IList<T> 强制转换为 IEnumerable<T> 只需要进行引用复制:

IList<T> l = new List<T>();
IEnumerable<T> e = l;

要将 IEnumerable<T> 强制转换为 List<T>,我们需要迭代每个元素或调用 ToList() 方法:

IEnumerable<T>.ToList(); 

或者可以将 IEnumerable<T> 传递给 List<T> 构造函数,该构造函数会在其内部执行相同的迭代操作。

List<T> l = new List<T>(e);

您认为哪种情况更有效率?在实践中,您更喜欢哪种情况?

1个回答

21

就效率而言,两者都是接口,因此效率取决于您返回的实际具体类。作为经验法则,您应该始终返回在对象层次结构中最高的适用于此方法的使用者的类型。在你的情况下是 IEnumerable<T>。如果该类的使用者需要添加元素、按索引访问元素或删除元素,则最好使用 IList<T>

所以像一直以来编程一样:这取决于情况:-)


例如,如果我实现了一个返回'IEnumerable<T>'的方法,然后在开发的另一个阶段中,我可能需要拥有'IList<T>',在这种情况下,我需要将'IEnumerable<T>'强制转换为'IList<T>'。此外,我可以复制此方法以创建新方法,该方法返回'IList<T>'。但我认为复制并不是一个好选择。但是,从'IEnumerable<T>'到'IList<T>'的转换只是引用复制,而从'IList<T>'到'IEnumerable<T>'则是每个元素的复制。但是,创建'IList<T>'需要更多的资源,而不是创建'IEnumerable<T>'。 - angularrocks.com
不,那些是接口。它们只是不占用任何资源的契约。只有具体类需要资源。当您在 IEnumerable<T> 上调用 ToList 扩展方法时,这只是创建一个 new List<T> 并将可枚举对象提供给构造函数。当然,底层元素不会被复制,因此您只是实例化一个不应占用太多内存的对象。底层可枚举对象是通过引用存储的。 - Darin Dimitrov
1
是的,我同意,“始终返回对象层次结构中最高的类型”,这绝对是正确的方式。我认为这就是这个问题的答案。 - angularrocks.com
1
是的,我有点混淆了。将“List<T>”强制转换为“IEnumerable<T>”只是引用复制,但是从“IEnumerable<T>”到“List<T>”需要对每个元素进行复制。但是,返回“IList<T>”的方法比返回“IEnumerable<T>”的方法需要更多的资源。 - angularrocks.com

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接