C#2.0中的Yield关键字行为

时间:2011-06-15 10:02:46

标签: c# yield

在一个方法中,我产生一个我重用的自定义对象。后来再次屈服。

private IEnumerable<DistributorMonthlyComparisonData> ExtractMonthlyAggregate(String CSVFilepath)
{
    DistributorMonthlyComparisonData unitData = new DistributorMonthlyComparisonData();
    while (!reader.EndOfStream)
        {
            if(something){
                // fill unitData
                }
            else{
                 yield return unitData;
                }
        }
}

在我的程序中的另一个对象中,我以这种方式调用所述方法:

List<DistributorMonthlyComparisonData> distribList = new List<DistributorMonthlyComparisonData>();
foreach (DistributorMonthlyComparisonData result in ExtractMonthlyAggregate(percorso))
  {
    distribList.Add(result);
  }

如果我没有在屈服方法中创建,则在每次屈服之后,创建一个新对象

unitData = new DistributorMonthlyComparisonData();

我得到的只是相同对象的列表。

我想知道:这是因为unitData作为引用传递,因此List只是对同一个相同对象的引用列表吗?每次更改正在传递的unitData对象的哈希值时创建一个新的unitData()?

请赐教。 :)

编辑我对为什么发生这种情况感兴趣。 我曾经认为框架应该在对象上进行copy-on-write,所以基本上产生一个对象然后修改它的属性然后再次产生它应该导致两个不同的对象被添加到列表中。

4 个答案:

答案 0 :(得分:3)

C#具有类类型的引用语义,因此您对正在返回的引用是正确的。

关于其余部分的旁注:

yield return / yield break将继续将它们放入的循环。因此,循环之前的代码仅在输入循环之前执行一次。您必须new将您返回的对象放在循环中。

即,你必须替换

DistributorMonthlyComparisonData unitData = new DistributorMonthlyComparisonData();
while (!reader.EndOfStream) {
    ...

while (!reader.EndOfStream) {
    DistributorMonthlyComparisonData unitData = new DistributorMonthlyComparisonData();
    ...

答案 1 :(得分:2)

  

我想知道:这是因为unitData作为引用传递,因此List只是对同一个相同对象的引用列表吗?

完全。

  

每次更改正在传递的unitData对象的哈希值时创建一个新的unitData()?

这取决于DistributorMonthlyComparisonData的GetHashCode()实现。

答案 2 :(得分:1)

对象初始化只会发生一次。执行将从第二次迭代开始从while循环继续。这就是对象集合具有相同对象实例的原因。

答案 3 :(得分:0)

  

每次更改正在传递的unitData对象的哈希值时创建一个新的unitData()?

     

没有GetHashCode()的实现,DistributorMonthlyComparisonData只是属性的集合。

GetHashCode()的默认实现不保证其返回值。因此,如果您没有自定义实现,则不应对此有任何期望。

当您为类型定义相等性时(通过覆盖Equals),您还必须覆盖GetHashCode,并保证比较相等的对象具有相同的哈希码。