LINQ Except() 的意外行为

4

我遇到了LINQ Except方法的奇怪行为,我不理解。我完全可以重新编写代码,以使其正常工作,这不是我的问题。我只是想理解它为什么会失败:

public void MyMethod(MyClass whatever, params object[] values){ // called with values = [ "mystr1", "mystr2", true, true ] 
  var valuesOfType = values.OfType<MyType>().ToList(); // valuesOfType is Empty List Count = 0
  values = values.Except(valuesOfType ).ToArray(); // values = [ "mystr1", "mystr2", true ] 
}

通过使用空列表应用 Except(),最后一个值从 values 中消失了!这是怎么可能的呢?我在调试器立即窗口中重新运行了该行代码,它没有被截断为 2 个元素。对 values 进行自我赋值不是问题,我尝试了另一个变量,它仍然被截断。这里发生了什么?
注: MyType 只是一个具有一个 get 属性的简单类型。
虽然问题已经得到解答,但如果有人想要查看可重现的控制台应用程序,可以参考以下内容:
namespace ConsoleApp1
{
    using System;
    using System.Linq;

    class Program
    {
        static void Main(string[] args)
        {
            var para = new object[] {"str1", "str2", true, true};
            var temp = new TestClass(new Dummy1(), para);
        }

        public class TestClass
        {
            public TestClass(Dummy1 dummy1, params object[] values)
            {
                var valuesOfType = values.OfType<Dummy2>().ToList();
                values = values.Except(valuesOfType).ToArray();

                foreach (var value in values)
                {
                    Console.WriteLine(value);
                }
                
                Console.ReadKey();
            }
        }

        public class Dummy1
        {
        }

        public class Dummy2
        {
        }
    }
}
1个回答

4
由于LINQ Except产生一个集合差异,因此它会移除重复项。来自文档的解释如下:

该方法返回第一个序列中不在第二个序列中出现的元素,而不是返回第二个序列中不在第一个序列中出现的元素。只返回唯一的元素。

在你的情况下,你有两个true值,因此只返回一个。

这意味着 list.Except(emptylist) 等于 list.Distinct() 吗? - Chrᴉz remembers Monica
基本上是的。它的实现首先创建一个包含第一个序列元素的集合,然后排除第二个序列中的元素(如果有)。如果没有任何元素被排除,则它只会从第一个序列创建一个集合。 - Evk
哇,谢谢!那完全解释了。正如他们所说,阅读文档...... - Maxim Zabolotskikh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接