c# - JOIN 对象集合的多个属性的正确方法?

标签 c# .net linq join

假设我有一个对象,其中以下 3 个属性(其他已被省略)构成了一个“唯一”的 Plan 对象(如果它们与另一个 Plan 对象中的相同值相等)。

public class Plan
{
    public int ID { get; set; }
    public Plan Parent { get; set; }
    public ID SomeOtherProperty { get; set; }
}

这是我的 Join 代码,其中省略了 Join 运算符的匿名方法 (我知道默认情况下此代码不起作用):

oldPlans
    .Join(newPlans, o => o, n => n, (o, n) => new { Old = o, New = n })
    .ForEach(e =>
    {
        ...
    });

我想对两个 Plan 对象集合执行 C# Join。我理解一种方法是对连接属性使用匿名方法,写出这三个属性。

但是有不同的方法吗?我可以重写 GetHashCode 吗?当我尝试这个时,它似乎并没有调用那个方法。我也尝试覆盖 Equals 但它似乎也没有调用它。我应该覆盖 ==!= 运算符吗?我可以为关键选择器字段显式调用 .GetHashCode()(假设我覆盖了它)吗?

是否可以让这个 Join 检查这两个对象的相等性而不使键选择器复杂化?谢谢。

最佳答案

您的代码对我来说工作正常 - 通过 ReferenceSource 进行跟踪,默认比较最终使用的是 ObjectEqualityComparer它调用了 Equals(),所以你的想法是正确的。

所以这取决于您如何实现 EqualsGetHashCode。如果你重写一个,你应该重写两个,如 MSDN states :

CAUTION: If you override the GetHashCode method, you should also override Equals, and vice versa. If your overridden Equals method returns true when two objects are tested for equality, your overridden GetHashCode method must return the same value for the two objects.

请注意您的 ID 类还需要正确处理这两种方法,因为 Plan 应该使用它来检查是否相等并获取哈希码。

这个程序对我有用,只打印带有 ID=2 的第二个条目(请注意,为了简单起见,我制作了 SomeOtherPropertyint 但这不会影响方法或代码):

class Program
{
    public class Plan
    {
        public int ID { get; set; }
        public Plan Parent { get; set; }
        public int SomeOtherProperty { get; set; }

        // added to show we don't care about this
        public string IgnoreMe { get; set; }

        public Plan(int id, int other, Plan parent, string ignore)
        {
            this.ID = id;
            this.SomeOtherProperty = other;
            this.Parent = parent;
            this.IgnoreMe = ignore;
        }

        public override bool Equals(object obj)
        {
            Plan other = (Plan)obj;
            // just check the relevant properties
            return this.ID == other.ID
                && this.SomeOtherProperty == other.SomeOtherProperty
                && this.Parent == other.Parent;

            // .. or alternatively
            //return (new { ID, SomeOtherProperty, Parent })
            //    .Equals(new { other.ID, other.SomeOtherProperty, other.Parent });
        }

        // nicked from http://stackoverflow.com/a/4630550/1901857
        public override int GetHashCode()
        {
            return new { ID, SomeOtherProperty, Parent }.GetHashCode();
        }

        // just to help debug
        public override string ToString()
        {
            return string.Format("[ID: {0}, Other:{1}, Parent:{2}]", ID, SomeOtherProperty, Parent);
        }
    }

    static void Main(string[] args)
    {
        var parentPlans = new Plan[] {
            new Plan(101, 2, null, "parent1"),
            new Plan(102, 3, null, "parent2"),
            new Plan(103, 4, null, "parent3"),
            new Plan(104, 5, null, "parent4")
        };

        List<Plan> oldPlans = new List<Plan>(new Plan[] {
            new Plan(1, 2, parentPlans[0], "old1"),
            new Plan(2, 3, parentPlans[1], "old2"),
            new Plan(3, 4, parentPlans[2], "old3"),
            new Plan(4, 5, parentPlans[3], "old4")
        });

        List<Plan> newPlans = new List<Plan>(new Plan[] {
            new Plan(11, 2, parentPlans[0], "new1"), // different ID
            new Plan(2, 3, parentPlans[1], "new2"),  // same
            new Plan(3, 14, parentPlans[2], "new3"), // different other ID
            new Plan(4, 5, parentPlans[2], "new4")   // different parent
        });

        foreach (var e in
            oldPlans.Join(newPlans, o => o, n => n, (o, n) => new { Old = o, New = n }))
        {
            Console.WriteLine(e.Old + " / " + e.New);
        };
    }
}

如果您认为您对 EqualsGetHashCode 的实现应该有效,那么请将它们张贴在问题中,也许它们不太正确。

关于c# - JOIN 对象集合的多个属性的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27779397/

相关文章:

C# 程序集位置解析

c# - 接收字符串作为内存流并进行编码后,将添加更多字符

c# - 在1个基本类和2个WPF窗口之间传递数据

c# - 如何在 c# 中使用 linq 拆分字符串以 "&lt;input "开头的字符串

c# - 如何将 linq var 数据类型传递给方法?

c# - 可选输出参数

c# - 在共享大小组旁边为网格列提供最小宽度

c# - 可为空的日期时间异常

c# - 什么会导致此代码产生文件锁定错误?

c# - 在 C# 中交换字典类型参数的复杂性