2011-12-22 68 views
2

我有這個代碼:這2個片段嚴格等效嗎?

foreach (object obj in _Destinations) 
{ 
    obj = _ItemsSource; 
} 

這是產生錯誤

不能分配給 'OBJ',因爲它是一個 '的foreach迭代變量'

所以我「盤旋「與以下代碼的問題:

for (int i = 0; i < _Destinations.Count; i++) 
{ 
    _Destinations[i] = _ItemsSource; 
} 

這適用於我的實際案例,但我不確定這是否與任何類型的對象完全相同。是這樣嗎?

編輯:_Destinations是List<object>

+0

這個線程可能會讓人感興趣,爲什麼'foreach'循環爲'for'循環表現出不同的行爲:http://stackoverflow.com/questions/5650705/in-c-why-cant-i-modify-the-成員的價值型實例在一個foreach循環 – keyboardP 2011-12-22 13:12:29

回答

2

這絕對是同樣的事情:首先,第二個作品,而第一個不:)

的原因第一個代碼段不起作用是因爲它使用了iterat或從_Distance列表,並且不可能通過IEnumerable<T>的迭代器分配給原始集合。第二個片段使用[index]來訪問基礎列表或數組。這個構造允許閱讀和寫作;這就是它工作的原因。

只要以相同的順序訪問列表或數組的所有元素,兩個構造都是相同的。

+0

是的,當然,我的問題是「如果第一個代碼可以編譯,第二個代碼是否可以嚴格等價?」 :) Semms是「是」,所以這很酷:) – 2011-12-22 13:15:53

+0

@GuillaumeSlashy它只會在邏輯上等效。在引擎蓋下,即使集合允許,第一段代碼也不會使用索引。換句話說,如果你使用列表,沒有區別;如果您實施自己的清單,則會有顯着差異。 – dasblinkenlight 2011-12-22 13:21:05

+0

我將使用Lists,ObservableCollections和IEnumerables。所以這相當於? – 2011-12-22 13:26:47

1

我猜_Destinations是值類型的集合。

forach循環會爲循環的每個「循環」創建一個元素的副本,並且最終只會更改副本,而不更改您正在迭代的實際集合。

for循環中,您正在使用索引更改實際集合。

所以不,它們並不完全等效。

對於引用類型,這是不是在同樣的意義,因爲這兩個集合中的元素,並通過在foreach 參考同一個對象,而正確的對象創建的副本問題將如果使用不考慮改變了foreachfor環(至少當你使用它像這樣)

+0

downvoter,照顧詳細? – 2011-12-22 13:15:31

+0

爲什麼你會猜測它是一個值類型的集合?如果您有一個類對象Foos的集合,重新分配循環變量將不會違法。即使它不是非法的,在循環內重新分配一個引用類型的變量仍然不會反映在集合內部。 – 2011-12-22 13:17:02

0

您應該閱讀有關IEnumerableIEnumerator以使您的foreach塊正常工作。

1

這顯然不是一回事,因爲你的結果是不同的!一個出錯,另一個出錯。

避開這種差異,你的第一個錯誤是在foreach中修改循環變量是非法的結果。你的第二個設法通過迭代for並分配給索引位置來完全避開這個問題。只要你有一個可寫的,可索引的集合,比如列表或數組,這將繼續爲你工作。如果您正在處理不可寫或不可索引的集合,例如簡單的IEnumerableReadOnlyCollection<T>,那麼您將無法使用此機制覆蓋元素,因爲該序列是隻讀的。

1

Foreach適用於任何IEnumerable,這是一個對象的最基本的合同,它是某種其他對象的某種聚集,列表,集合等。 IEnumerable不提供工具來覆蓋聚合中的項目,甚至沒有添加或刪除項目。在IEnumerable中,也沒有索引的概念。因此你不能爲foreach迭代變量賦值。

其他代碼片段需要一個集合,它實現了IList這是一個更具體的合同,它允許進行集合操作並且還有一個索引的概念。因此第二個代碼片段起作用。

第二個例子中的IList在理論上可以實現枚舉,但它不會按照索引升序排列,但這是不太可能的,因此您可以將兩種迭代技術視爲相同。