3

因此,以下 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);
    }
4

4 回答 4

5

它们EqualityComparer<T>.Default用于相等比较和Comparer<T>.Default有序比较。

MSDN -EqualityComparer<T>.Default备注:

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

MSDN -Comparer<T>.Default备注:

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

于 2010-02-25T21:39:10.850 回答
4

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

改成:

var singleFoo = _barCollection.SingleOrDefault(b => b.Foo.Equals(foo));
于 2010-02-25T21:41:35.650 回答
0

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

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

虽然使用.Equals是一种解决方案,但对我来说感觉不自然?

于 2010-07-13T15:43:21.933 回答
0

您还需要覆盖 == 运算符

于 2010-02-25T21:40:56.617 回答