简体   繁体   English

如何在C#中覆盖接口的equals运算符==?

[英]How do I override the equals operator == for an Interface in C#?

I have defined the following interface 我已经定义了以下界面

public interface IHaveAProblem
{
    string Issue { get; set; }
}

And here is the implementation of the IHaveAProblem 这是IHaveAProblem的实现

public class SomeProblem : IHaveAProblem
{
    public string Issue { get; set; }

    public override bool Equals(object obj)
    {
        SomeProblem otherObj = obj as SomeProblem;

        if (otherObj == null)
        {
            return false;
        }

        return this.Issue == otherObj.Issue;
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }

    public static bool operator ==(SomeProblem rhs, SomeProblem lhs)
    {
        // Null check
        if (Object.ReferenceEquals(rhs, null) || Object.ReferenceEquals(lhs, null))
        {
            if (Object.ReferenceEquals(rhs, null) && Object.ReferenceEquals(lhs, null))
            {
                // Both are null.  They do equal each other
                return true;
            }

            // Only 1 is null the other is not so they do not equal
            return false;
        }

        return rhs.Equals(lhs);
    }

    public static bool operator !=(SomeProblem rhs, SomeProblem lhs)
    {
        // Null check
        if (Object.ReferenceEquals(rhs, null) || Object.ReferenceEquals(lhs, null))
        {
            if (Object.ReferenceEquals(rhs, null) && Object.ReferenceEquals(lhs, null))
            {
                // Both are null.  They do equal each other
                return false;
            }

            // Only 1 is null the other is not so they do not equal
            return true;
        }

        return !rhs.Equals(lhs);
    }
}

When I use the object I can get the correct results for the == compare. 当我使用对象时,我可以得到== compare的正确结果。

SomeProblem firstTest = new SomeProblem()
    {
        Issue = "Hello World"
    };

SomeProblem secondTest = new SomeProblem()
    {
        Issue = "Hello World"
    };

// This is true
bool result = firstTest == secondTest;

However when I try to compare the interfaces it is doing a memory compare rather than the operator == on SomeProblem 但是,当我尝试比较接口时,它正在进行内存比较而不是SomeProblem上的operator ==

IHaveAProblem firstProblem = new SomeProblem()
    {
        Issue = "Hello World"
    };

IHaveAProblem secondProblem = new SomeProblem()
    {
        Issue = "Hello World"
    };

Is it possible have the interface use the == on SomeProblem rather than a memory compare? 是否有可能让接口在SomeProblem上使用==而不是内存比较?

I know I can do a firstProblem.Equals(secondProblem) and get the proper result, however I am creating a frame work and I will not know how it is used in the end. 我知道我可以做一个firstProblem.Equals(secondProblem)并获得正确的结果,但是我正在创建一个框架工作,我不知道它最终是如何使用的。 I thought == would work correctly. 我以为==会正常工作。

The operator == is static. 运算符==是静态的。 You cannot define static methods for interfaces in C#. 您无法在C#中为接口定义静态方法。 Also, for all operators at least one of the argument types needs to be of the same type as the class it is defined in, therefore: No operator overloading for interfaces :( 此外,对于所有运算符,至少有一个参数类型需要与它所定义的类具有相同的类型,因此:没有运算符重载接口:(

What you CAN do is use an abstract class instead - and define the operator there. 您可以做的是使用抽象类 - 并在那里定义运算符。 Again, the operator may NOT be virtual (since static methods cannot be virtual...) 同样,运算符可能不是虚拟的(因为静态方法不能是虚拟的......)

[Edited, reason see comment.] [编辑,理由见评论。]

IIRC (and I could be wrong here), C# interfaces don't allow operator overloading. IIRC(我可能在这里错了),C#接口不允许运算符重载。

But in this case that's okay. 但在这种情况下,没关系。 The == operator normally maps to reference equality. ==运算符通常映射到引用相等。 It sounds like you want value equality, and that means you want to force them to override the .Equals() (and consequently also .GetHashCode() ) functions. 听起来你想要值相等,这意味着你想强制它们覆盖.Equals() (以及.GetHashCode() )函数。 You do that by having your interface inherit from IEquatable() . 你通过让你的接口继承IEquatable()做到这一点。

I konw, this is an old question, but all examples provided show how to compare two class instances, and no one points out how to compare two interface instances. 我知道,这是一个老问题,但提供的所有示例都显示了如何比较两个类实例,没有人指出如何比较两个接口实例。

In some cases, this is the DRYest way to compare interfaces. 在某些情况下,这是比较接口的DRYest方法。

public interface IHaveAProblem
{
    string Issue { get; set; }
}

public class IHaveAProblemComparer : IComparer<IHaveAProblem>, IEqualityComparer<IHaveAProblem>
{
    public int Compare(IHaveAProblem x, IHaveAProblem y)
    {
        return string.Compare(x.Issue, y.Issue);
    }

    public bool Equals(IHaveAProblem x, IHaveAProblem y)
    {
        return string.Equals(x.Issue, y.Issue);
    }

    public int GetHashCode(IHaveAProblem obj)
    {
        return obj.GetHashCode();
    }
}

Usage? 用法?

IHaveAProblemComparer comparer = new IHaveAProblemComparer();

List<IHaveAProblem> myListOfInterfaces = GetSomeIHaveAProblemObjects();
myListOfInterfaces.Sort(comparer); // items ordered by Issue

IHaveAProblem obj1 = new SomeProblemTypeA() { Issue = "Example1" };
IHaveAProblem obj2 = new SomeProblemTypeB() { Issue = "Example2" };

bool areEquals = comparer.Equals(obj1, obj2); // False

Have you tried implementing IComparable? 您是否尝试过实施IComparable?

Like this: 像这样:

public interface IHaveAProblem : IComparable
{
    string Issue { get; set; }
}

And then in the implementation of the class: 然后在类的实现中:

public class SomeProblem : IHaveAProblem
{
    public string Issue { get; set; }

    ...

    public int CompareTo(object obj)
    {
        return Issue.CompareTo(((SomeProblem)obj).Issue);
    }
}

Note that, this works only when you compare two instances of SomeProblem, but not any other implementations of the IHaveAProblem interface. 请注意,这仅适用于比较SomeProblem的两个实例,而不是IHaveAProblem接口的任何其他实现。

Not sure if there could occur a NullReferenceException. 不确定是否可能发生NullReferenceException。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM