2008-12-17 135 views

回答

46

一般而言,您可以在其上执行For Each的集合,以实现IEnumerator接口。此接口只有两种方法,MoveNextReset以及一个属性Current

基本上,当您在集合上使用For Each时,它会调用MoveNext函数并读取返回的值。如果返回值为True,则表示集合中存在有效元素,并通过Current属性返回元素。如果集合中没有更多元素,则函数MoveNext返回False,并且退出迭代。

从以上的解释,很显然的是,For Each不跟踪当前位置的收集等的回答你的问题是一个短期没有

但是,如果您仍然想知道您是否在集合中的最后一个元素上,可以尝试以下代码。它检查(使用LINQ)当前项目是否是最后一个项目。

For Each item in Collection 
    If item Is Collection.Last Then 
     'do something with your last item' 
    End If 
Next 
+0

包含解决方案的一个非常好的解释。 – Jonathan 2011-10-19 14:56:05

1

检查元素是否是容器的最后一个元素。

为什么你想这样做?
你可以在循环之后放置指令。 (你在最后一个元素上执行)

12

使用For循环代替ForEach可能会更容易。但是,类似地,您可以在ForEach循环中保留一个计数器,并查看它是否等于yourCollection.Count - 1,那么您就处于最后一次迭代中。

+0

好了,这就是我通常做,如果我需要这样做,但我只是觉得有一个聪明的方法来确定这在一个For Each或什么的。 – EdenMachine 2008-12-20 01:15:11

0

如果您绑定到IEnumerable。你是否必须进入foreach循环?如果没有,你可以在foreach循环之前声明一个变量。在循环中设置它。然后,在循环后使用它(如果它不为空)

6

使用foreach,直到它已经太晚(即你没有进入循环),你无法知道它。

请注意,我假设您使用的东西只有IEnumerable接口。如果你有一个列表,数组等,然后按照这里使用.Count或类似的其他答案来找出有多少项目,因此你可以跟踪你在收藏中的位置。

但是,只有IEnumerable/IEnumerator,如果你使用foreach,没有办法知道它是否还有更多。

如果您需要知道这一点,请自行使用IEnumerable,这是foreach所做的。

下面的解决方案是C#,但应该很容易翻译到VB.NET:

List<Int32> nums = new List<Int32>(); 
nums.Add(1); 
nums.Add(2); 
nums.Add(3); 

IEnumerator<Int32> enumerator = nums.GetEnumerator(); 
if (enumerator.MoveNext()) 
{ 
    // at least one value available 
    while (true) 
    { 
     // make a copy of it 
     Int32 current = enumerator.Current; 

     // determine if it was the last value 
     // if not, enumerator.Current is now the next value 
     if (enumerator.MoveNext()) 
     { 
      Console.Out.WriteLine("not last: " + current); 
     } 
     else 
     { 
      Console.Out.WriteLine("last: " + current); 
      break; 
     } 
    } 
} 
enumerator.Dispose(); 

这将打印:

not last: 1 
not last: 2 
last: 3 

诀窍是把当前值的副本,然后要求统计员试图进入下一个。如果失败了,你所做的副本确实是最后一个值,否则还有更多。

2

简短的回答:你不能

龙答:没有什么在的语义为每个允许您确定您是否正在运行的姓氏,名字或任何特定的循环语句。

对于每个都构建在IEnumerable和IEnumerable接口中,并且行为取决于您调用的实现。它是有效的,虽然混淆,因为你正在迭代的集合每次都以不同的顺序返回元素。幸运的是,列表<>不这样做。

如果您确实需要知道特定迭代是最后一个迭代,您可以确定最后一个元素(提前),然后在遇到该元素时采取不同的操作。

更容易的是检测第一个迭代(比如,通过布尔值),然后做一些不同的事情。

一个例子(C#,但VB将是相似的):

StringBuilder result = new StringBuilder(); 
bool firstTime = true; 
foreach(string s in names) 
{ 
    if (!firstTime) 
    { 
     result.Append(", "); 
    } 

    result.Append(s); 
    firstTime = false; 
} 
+0

你忘了firstTime = false;在第一次循环迭代之后。 – Dutchie432 2010-10-27 20:53:22

+0

哎呀!谢谢你的收获 - 现在已经修好了。 – Bevan 2010-10-28 08:45:00

1

它会更容易地使用for循环,而不是一个foreach,但你可以不喜欢

If item.Equals(itemCollection(itemCollection.Count)) Then 
    ... 
End If 

在你的ForEach循环中...假设对象已经正确地重写了Equals方法。

这可能比只使用For循环或在单独变量中跟踪当前索引的资源密集得多。

我不确定这是否是正确的语法,因为我已经使用VB很长一段时间了。

1

使用标准的“For Each”循环,你不能。 “for Each”循环的目的是让您专注于代替底层集合的数据。

0

那么有几个解决方法 假设您正在使用的CheckBoxList

工作那么这个代码示例可能帮助:

Dim count As Integer = 0 
Dim totalListCount As Integer = CheckBoxList.Items.Count() 
For Each li In CheckBoxList.Items 
     count += 1 
      // This is the Last Item 
     If count = totalListCount THEN 
      // DO Somthing..... 
     END IF 
NEXT  
1

我继续回来到这个职位,所以我决定坐下来,想想这个问题,我想出了这个:

For Each obj In myCollection 
     Console.WriteLine("current object: {0}", obj.ToString) 

     If Object.ReferenceEquals(obj, myCollection.Last()) Then 
      Console.WriteLine("current object is the last object") 
     End If 
    Next 

如果您愿意,甚至可以将If...Then...End If语句简化为单行。我不确定在每次迭代中调用.Last()对性能有很大影响,但是如果这样可以让您在夜晚保持清醒状态,则始终可以将其分配给循环外的变量。

1

此代码示例可能有助于

For Each item in Collection 
    If ReferenceEquals(Collection.Item(Collection.Count - 1), item) Then 
    'do something with your last item' 
    End If 
Next 
0

这里是一个简单的事情,我不知道这是否是政治上正确的,但它的工作原理

for each item in listOfThings 
    if(item = listOfThings.last)then 
     'you found the last loop 
    end if 
next