C# 何时使用每个T[],列出<;T>;,IEnumerable<;T>;?
我通常会发现自己在做这样的事情:C# 何时使用每个T[],列出<;T>;,IEnumerable<;T>;?,c#,ienumerable,idioms,C#,Ienumerable,Idioms,我通常会发现自己在做这样的事情: string[] things = arrayReturningMethod(); int index = things.ToList<string>.FindIndex((s) => s.Equals("FOO")); //do something with index return things.Distinct(); //which returns an IEnumerable<string> string[]things=
string[] things = arrayReturningMethod();
int index = things.ToList<string>.FindIndex((s) => s.Equals("FOO"));
//do something with index
return things.Distinct(); //which returns an IEnumerable<string>
string[]things=arrayReturningMethod();
int index=things.ToList.FindIndex((s)=>s.Equals(“FOO”);
//用索引做些什么
返回东西。不同的()//返回一个IEnumerable
我发现所有这些类型/接口的混合有点让人困惑,这让我的潜在性能问题触角发痒(当然,在证明正确之前,我会忽略这一点)
这是一个惯用且恰当的C#还是有更好的替代方法来避免来回转换以访问正确的方法来处理数据
编辑:
问题实际上有两个方面:
- 什么时候可以直接使用IEnumerable接口或数组或列表(或任何其他IEnumerable实现类型)(在接受参数时)
- 您是否应该在IEnumerables(实现未知)和列表、IEnumerables和数组、数组和列表之间自由移动,或者是非惯用的(有更好的方法来实现)/非性能的(通常不相关,但在某些情况下可能是)/只是简单的丑陋(不可维护、不可读)
在这种情况下,与你描述的情况相似的每一种情况都是完全不同的,以防止关于转换你的类型的教条规则;但是,选择一个尽可能提供所需接口的数据结构,而不必将不必要的元素复制到新的数据结构,这通常是一个好的做法。一个好的经验法则是始终使用IEnumerable(在声明变量/方法参数/方法返回类型/属性等时)除非你有充分的理由不这么做。到目前为止,它是与其他(尤其是扩展)方法最兼容的类型。好吧,你有两个苹果和一个桔子在比较 这两个苹果是数组和列表
- C#中的数组是一个内置垃圾收集的C样式数组。使用它们的好处是它们的开销很小,假设你不需要移动东西。糟糕的是,当您添加、删除内容或以其他方式更改数组时,它们的效率会降低,因为内存会被洗牌
- 列表是C#风格的动态数组(类似于C++中的向量类)。这会带来更多的开销,但是当您需要大量移动东西时,它们会更有效,因为它们不会试图保持内存使用的连续性
希望这能消除一点迷雾。在我看来,问题在于您没有费心学习如何搜索数组。提示:或取决于数组是否已排序
您是对的,转换为列表是一个坏主意:它浪费空间和时间,使代码可读性降低。此外,盲目向上转换到
IEnumerable
会减慢速度,也会完全阻止使用某些算法(如二进制搜索)。在实际出现性能问题之前,忽略“性能问题”天线是正确的。大多数性能问题都是由于执行了太多的I/O或太多的锁定或其中一个操作出错造成的,这些都不适用于此问题
我的一般做法是:
当然,这只是一个粗略的指导方针。请尝试在相同的代码库中遵循相同的模式——跳跃式的代码样式使维护代码编写人员更难进入您的思维模式。关于性能
- 从List转换到T[]需要将原始列表中的所有数据复制到新分配的数组中
- 从T[]到List的转换还包括将原始列表中的所有数据复制到新分配的列表中
- 从List或T[]转换为IEnumerable需要转换,这需要几个CPU周期
- 从IEnumerable到List的转换需要向上转换,这也需要几个CPU周期
- 从IEnumerable到T[]的转换也需要向上转换
- 您不能将IEnumerable强制转换为t[]或List,除非
public int[] DoSomething(IEnumerable<int> inputs) { //... } public List<int> DoSomethingElse(IList<int> inputs) { //... }