c#中使用foreach是非常方便的操作,foreach的執行效率比for高,foreach可以在不用知道長度的情況下進行遍歷,但是for一般要知道長度才能遍歷,否則要在循環的內部進行控制。 foreach在c#中一般用於操作集合對象。但我在用foreach循環刪除元素時遇到了麻煩,比如這樣的代碼:
foreach (Class.Rectangle rec in rectangles)
{
if (this.searchedlayer.Equals(rec.Outlayer) && rec.Number == 3)
{
this.selectedrectangle = rec;
this.rectangles.Remove(this.selectedrectangle);
}
}
這樣寫的話運行會出錯:集合已修改,可能無法執行枚舉操作 foreach。
因為foreach是取只讀的,在取的時候數據不能變(包括修改,刪除,添加等),當修改了集合的元素時,地址可能發生某種改變,所以不跳出循環繼續遍歷時,就可能出現引用找不到的情況。所以要把代碼改成這樣:
foreach (Class.Rectangle rec in rectangles)
{
if (this.searchedlayer.Equals(rec.Outlayer) && rec.Number == 3)
{
this.selectedrectangle = rec;
break;
}
}
this.rectangles.Remove(this.selectedrectangle);
如果要循環刪除可以增加一個for循環:
for (int i = 0; i < rectangles.Count; i++)
{
foreach (Class.Rectangle rec in rectangles)
{
if (this.searchedlayer.Equals(rec.Outlayer) && rec.Number == 3)
{
this.selectedrectangle = rec;
break;
}
}
this.rectangles.Remove(this.selectedrectangle);
}
只讀的原因:
namespace System.Collections { // 摘要: // 支持對非泛型集合的簡單迭代。 [ComVisible(true)] [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")] public interface IEnumerator { // 摘要: // 獲取集合中的當前元素。 // // 返回結果: // 集合中的當前元素。 // // 異常: // System.InvalidOperationException: // 枚舉數定位在該集合的第一個元素之前或最后一個元素之后。 object Current { get; } bool MoveNext(); void Reset(); } } namespace System.Collections { // 摘要: // 公開枚舉數,該枚舉數支持在非泛型集合上進行簡單迭代。 [ComVisible(true)] [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")] public interface IEnumerable { // 摘要: // 返回一個循環訪問集合的枚舉數。 // // 返回結果: // 可用於循環訪問集合的 System.Collections.IEnumerator 對象。 [DispId(-4)] IEnumerator GetEnumerator(); } }
每個實現的迭代器,返回類型必須為 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。foreach中的迭代變量是即為IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>類型。從上面的接口可以看出,object Current是只讀的,因此,foreach迭代變量只能是只讀的。
另:
foreach中的迭代變量本來就是只讀,不可修改的。
對值類型中的屬性賦值,會改變值類型對象在棧上的內存分步,所以實際上就是對值類型對象本身重新賦值了