LINQ - 过滤和更新IEnumerable集合的属性

时间:2016-06-20 20:27:11

标签: c# linq

如果我正在使用ForEach中的引用,我试图理解.Except.ForEach的连接如何在LINQ表达式中起作用。

我有一个IEnumaerable对象集合,我的要求是更新原始集合中对象子集的属性。我尝试在表达式中使用except和foreach,但该属性未更新。

private Size[] FilterCollection()
{    
   var collection1 = { {
      "Bytes": 56,
      "Name": "low",
      "Code": "XS"
    },
    {
      "Bytes": 123,
      "Name": "medium",
      "Code": "M"
    },
    {
      "Bytes": 8888,
      "Name": "large",
      "Code": "M"
    }
  };

  var collection2 = { {
      "Bytes": 56,
      "Name": "low",
      "Code": "XS"
    },
    {
      "Bytes": 8888,
      "Name": "large",
      "Code": "M"
    }
  };                     

 collection1= collection1.ToArray();
 collection1.Except(collection2, new CustomComparer()).ForEach(x=> x.Code= null);
 return collection1;
}

 private class CustomComparer: IEqualityComparer<Size>
    {
        public bool Equals(Size x, Size y)
        {
            return x.Name == y.Name;
        }

        public int GetHashCode(Size obj)
        {
            return obj.Name.GetHashCode();
        }
    }

输出:

{ 
    {
      "Bytes": 56,
      "Name": "low",
      "Code": "XS"
    },
    {
      "Bytes": 123,
      "Name": "medium",
      "Code": null
    },
    {
      "Bytes": 8888,
      "Name": "large",
      "Code": "M"
    }
}

但是当我将.Aoray()连接到表达式的其余部分时,&#39; Code&#39;财产未更新

collection1.ToArray().Except(collection2, new CustomComparer()).ForEach(x=> x.Code= null);
return collection1;

输出:

{ 
    {
      "Bytes": 56,
      "Name": "low",
      "Code": "XS"
    },
    {
      "Bytes": 123,
      "Name": "medium",
      "Code": "M"
    },
    {
      "Bytes": 8888,
      "Name": "large",
      "Code": "M"
    }
}

有人可以解释这两个表达式之间的区别是什么吗?

2 个答案:

答案 0 :(得分:0)

如果您的Size类覆盖Equals(),则可以使用Except<T>()方法而不使用IEqualityComparator。要使用您使用的Except<>(second, comparor)方法,需要您构建自己的自定义比较器类。

选项1:

public class Size
{
    //Properties and stuff...

    public override Equals(object obj)
    {
        Size other = obj as Size;
        if (other != null)
            return other.Name == this.Name && other.Bytes == this.Bytes;
        return false;
    }
}

在您的方法中:

collection1.Except(collection2).ForEach(x => x.Code = null);

选项2:

public class MyComparator : IEqualityComparer<Size>
{
    public bool Equals(Size x, Size y)
    {
        return x.Name == y.Name && x.Bytes == y.Bytes;
    }

    public int GetHashCode(Size obj)
    {
        return obj.Bytes;
    }
}

在您的方法中:

collection1.Except(collection2, new MyComparator()).ForEach(x => x.Code = null);

答案 1 :(得分:-1)

调用chart.Series.Clear(); chart.Series[0].Items.Add(new DataPoint(1, 2)); 会创建一个包含linq查询结果的新数组。因此,它实际上是创建了可枚举结果的副本(请在此处查看deferred execution的解释)。在第一个示例中,您将新创建的数组分配到ToArray()变量中,然后在新数组上调用collection1Except。在第二个示例中,您正在创建新数组并在其上调用ForeachExcept方法,但您没有在变量中捕获数组。相反,你将返回原始的可枚举。

查看此链接以获取更多信息:https://msdn.microsoft.com/en-us/library/bb298736(v=vs.100).aspx