2011-12-22 67 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在理论上可以实现枚举,但它不会按照索引升序排列,但这是不太可能的,因此您可以将两种迭代技术视为相同。