C# Linq 扩展方法如何执行相等比较?

发布于 2024-08-23 04:21:41 字数 1868 浏览 15 评论 0原文

因此,以下 lambda 表达式不会返回集合中的任何元素,即使在逐步执行时我能够验证 1 个项目是否符合条件。我添加了该类的示例及其 IEquatable 实现。

...within a method, foo is a method parameter
var singleFoo = _barCollection.SingleOrDefault(b => b.Foo == foo);

上面没有返回任何内容。关于如何使上述表达式起作用有什么建议吗?

public class Foo: IEquatable<Foo> 
{
    public string KeyProperty {get;set;}
    public bool Equals(Foo other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.KeyProperty==KeyProperty;
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (Foo)) return false;
        return Equals((Foo) obj);
    }
    public override int GetHashCode()
    {
        return (KeyProperty != null ? KeyProperty.GetHashCode() : 0);
    }
}

为了确保我没有发疯,我创建了以下 nUnit 测试,该测试通过了:

    [Test]
    public void verify_foo_comparison_works()
    {
        var keyString = "keyValue";
        var bar = new Bar();
        bar.Foo = new Foo { KeyProperty = keyString };
        var basicFoo = new Foo { KeyProperty = keyString };
        var fromCollectionFoo = Bars.SingleFooWithKeyValue;
        Assert.AreEqual(bar.Foo,basicFoo);
        Assert.AreEqual(bar.Foo, fromCollectionFoo);
        Assert.AreEqual(basicFoo, fromCollectionFoo);
    }

尝试覆盖 == 和 !=:

    public static bool operator ==(Foo x, Foo y)
    {
        if (ReferenceEquals(x, y))
            return true;
        if ((object)x == null || (object)y == null)
            return false;
        return x.KeyProperty == y.KeyProperty;
    }
    public static bool operator !=(Foo x, Foo y)
    {
        return !(x == y);
    }

So, the following lambda expression is not returning any elements in the collection, even though while stepping through I was able to verify that 1 item matches the criteria. I've added a sample of the class with it's IEquatable implementation.

...within a method, foo is a method parameter
var singleFoo = _barCollection.SingleOrDefault(b => b.Foo == foo);

The above returns nothing. Any suggestions as to what to do to make the expression above work?

public class Foo: IEquatable<Foo> 
{
    public string KeyProperty {get;set;}
    public bool Equals(Foo other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.KeyProperty==KeyProperty;
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (Foo)) return false;
        return Equals((Foo) obj);
    }
    public override int GetHashCode()
    {
        return (KeyProperty != null ? KeyProperty.GetHashCode() : 0);
    }
}

To make sure I didn't go insane, I created the following nUnit test which passes:

    [Test]
    public void verify_foo_comparison_works()
    {
        var keyString = "keyValue";
        var bar = new Bar();
        bar.Foo = new Foo { KeyProperty = keyString };
        var basicFoo = new Foo { KeyProperty = keyString };
        var fromCollectionFoo = Bars.SingleFooWithKeyValue;
        Assert.AreEqual(bar.Foo,basicFoo);
        Assert.AreEqual(bar.Foo, fromCollectionFoo);
        Assert.AreEqual(basicFoo, fromCollectionFoo);
    }

Attempt at overriding == and !=:

    public static bool operator ==(Foo x, Foo y)
    {
        if (ReferenceEquals(x, y))
            return true;
        if ((object)x == null || (object)y == null)
            return false;
        return x.KeyProperty == y.KeyProperty;
    }
    public static bool operator !=(Foo x, Foo y)
    {
        return !(x == y);
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

昵称有卵用 2024-08-30 04:21:41

他们使用 EqualityComparer.Default用于相等比较和 Comparer.Default 用于有序比较。

MSDN - EqualityComparer.Default 备注:

Default 属性检查类型 T 是否实现了 System.IEquatable(Of T) 通用接口,如果是,则返回一个 使用该实现的 EqualityComparer(Of T)。否则,它返回一个 EqualityComparer(Of T),它使用 T 提供的 Object.EqualsObject.GetHashCode 覆盖代码>.

MSDN - Comparer.Default 备注:

此属性返回的 Comparer(Of T) 使用 System.IComparable(Of T) 通用接口 (IComparable在 C# 中,IComparable(Of T) 在 Visual Basic 中) 来比较两个对象。如果类型 T 未实现 System.IComparable(Of T) 泛型接口,则此属性返回一个 Comparer(Of T),它使用System.IComparable 接口。

They use EqualityComparer<T>.Default for equality comparisons and Comparer<T>.Default for ordered comparisons.

MSDN - EqualityComparer<T>.Default Remarks:

The Default property checks whether type T implements the System.IEquatable(Of T) generic interface and if so returns an EqualityComparer(Of T) that uses that implementation. Otherwise it returns an EqualityComparer(Of T) that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

MSDN - Comparer<T>.Default Remarks:

The Comparer(Of T) returned by this property uses the System.IComparable(Of T) generic interface (IComparable<T> in C#, IComparable(Of T) in Visual Basic) to compare two objects. If type T does not implement the System.IComparable(Of T) generic interface, this property returns a Comparer(Of T) that uses the System.IComparable interface.

美胚控场 2024-08-30 04:21:41

您没有重新定义 == 运算符。

更改为:

var singleFoo = _barCollection.SingleOrDefault(b => b.Foo.Equals(foo));

You are not redefining the == operator.

Change to:

var singleFoo = _barCollection.SingleOrDefault(b => b.Foo.Equals(foo));
溇涏 2024-08-30 04:21:41

您还需要覆盖 == 运算符

You need to also override the == operator.

无远思近则忧 2024-08-30 04:21:41

我在 IdentityKey 类(具有隐式 Guid 转换)中遇到了类似的问题 - 在这种情况下,包含 == 运算符 覆盖实际上并不可行。

我说这是不可行的,因为通过“混合”比较,我现在必须转换类型以避免 == 运算符重载的歧义。
ie. 而不是 if(guidValue = IdentityKeyValue) 它必须成为 if((IdentityKey)guidValue == IdentityKeyValue)

而使用 .Equals 是一个解决方案,我觉得不自然?

I've hit a similar problem with an IdentityKey class (that has implicit Guid conversions) - in this instance it's not really feasible to include an == operator override.

I say it's not feasible because with "mixed" comparisons I'll now have to cast the types to avoid ambiguity for the == operator overloads.
ie. Instead of if(guidValue = identityKeyValue) it has to become if((IdentityKey)guidValue == identityKeyValue)

Whilst using .Equals is a solution, it doesn't feel natural to me?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文