当foreach
通过一个通用的清单荷兰国际集团我经常想做些不同的事在列表中的第一个元素:
List
这将输出:
First object - do something special object Do something else object Do something else object Do something else
这一切都很好,花花公子.
但是,如果我的通用列表是值类型,则此方法将失败.
Listints = new List { 0, 0, 0, 0 }; foreach (int i in ints) { if (i == ints.First()) { System.Diagnostics.Debug.WriteLine("First int - do something special"); } else { System.Diagnostics.Debug.WriteLine("int Do something else"); } }
这将输出:
First int - do something special First int - do something special First int - do something special First int - do something special
现在我知道我可以重新编码以添加boolean
标志变量或传统for
循环,但我想知道是否有任何方法可以找出foreach循环是否在其循环的第一次迭代中.
好吧,您可以使用显式迭代对其进行编码:
using(var iter = ints.GetEnumerator()) { if(iter.MoveNext()) { // do "first" with iter.Current while(iter.MoveNext()) { // do something with the rest of the data with iter.Current } } }
bool标志选项(with foreach
)虽然可能更容易......这就是我(几乎)总是这样做的!
另一种选择是LINQ:
if(ints.Any()) { var first = ints.First(); // do something with first } foreach(var item in ints.Skip(1)) { // do something with the rest of them }
上面的缺点是它试图查看列表3次...因为我们知道它是一个列表,这很好 - 但如果我们只有一个IEnumerable
,那么迭代它一次是合理的(因为源可能无法重读().
前一段时间我写了SmartEnumerable(MiscUtil的一部分),它让你知道当前元素是第一个还是最后一个,以及它的索引.这可能对你有帮助......它是MiscUtil的一部分,它是开源的 - 你当然可以在相同的许可下使用SmartEnumerable.
示例代码(来自网页的c'n'p):
using System; using System.Collections.Generic; using MiscUtil.Collections; class Example { static void Main(string[] args) { Listlist = new List (); list.Add("a"); list.Add("b"); list.Add("c"); list.Add("d"); list.Add("e"); foreach (SmartEnumerable .Entry entry in new SmartEnumerable (list)) { Console.WriteLine ("{0,-7} {1} ({2}) {3}", entry.IsLast ? "Last ->" : "", entry.Value, entry.Index, entry.IsFirst ? "<- First" : ""); } } }
编辑:请注意,虽然它适用于具有不同引用的引用类型,但如果您给它一个列表,其中第一个引用在列表中的其他位置出现,它仍然会失败.
foreach(int i in ints.Take(1)) { //do first thing } foreach(int i in ints.Skip(1)) { //do other things }