使用==比较两个结构

JMK*_*JMK 48 c# struct equality

我试图在C#中使用equals(==)比较两个结构.我的结构如下:

public struct CisSettings : IEquatable<CisSettings>
{
    public int Gain { get; private set; }
    public int Offset { get; private set; }
    public int Bright { get; private set; }
    public int Contrast { get; private set; }

    public CisSettings(int gain, int offset, int bright, int contrast) : this()
    {
        Gain = gain;
        Offset = offset;
        Bright = bright;
        Contrast = contrast;
    }

    public bool Equals(CisSettings other)
    {
        return Equals(other, this);
    }

    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }

        var objectToCompareWith = (CisSettings) obj;

        return objectToCompareWith.Bright == Bright && objectToCompareWith.Contrast == Contrast &&
               objectToCompareWith.Gain == Gain && objectToCompareWith.Offset == Offset;

    }

    public override int GetHashCode()
    {
        var calculation = Gain + Offset + Bright + Contrast;
        return calculation.GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图将struct作为我的类中的属性,并且想要检查结构是否等于我尝试将其分配给的值,然后我继续这样做,所以我没有指示属性如果没有,就改变了,就像这样:

public CisSettings TopCisSettings
{
    get { return _topCisSettings; }
    set
    {
        if (_topCisSettings == value)
        {
            return;
        }
        _topCisSettings = value;
        OnPropertyChanged("TopCisSettings");
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在我检查相等性的行上,我收到此错误:

运算符'=='不能应用于'CisSettings'和'CisSettings'类型的操作数

我无法弄清楚为什么会这样,有人能指出我正确的方向吗?

Jen*_*ter 79

你需要重载==!=运算符.将此添加到您的struct:

public static bool operator ==(CisSettings c1, CisSettings c2) 
{
    return c1.Equals(c2);
}

public static bool operator !=(CisSettings c1, CisSettings c2) 
{
   return !c1.Equals(c2);
}
Run Code Online (Sandbox Code Playgroud)

  • "可能"与它无关; 在没有覆盖的情况下覆盖==是*非法*! (16认同)
  • 如果您关心性能,您应该考虑自己实现 `==` 运算符。上述实现会导致“装箱”,正如 [Microsoft](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing) 所描述的那样“计算成本很高”。特别是因为您可以只比较结构所包含的 4 个整数。 (4认同)
  • 不要忘记超载"!="运算符;) (2认同)

Han*_*ing 8

当您重写该.Equals()方法时,该==运算符不会自动重载。你需要明确地这样做。

另请参阅重写 Equals() 和运算符 == 的指南CA1815:重写值类型上的 equals 和运算符 equals


小智 5

您还可以使用 C# v9 以来的 Record 类型和 C# v10 以来的 [record struct] 值类型,以避免编写大量重复的代码。

有关更多详细信息,请参阅此处的 Microsoft 文档:

相等运算符(C# 参考)

在 C# 9.0 及更高版本中可用,记录类型支持 == 和 != 运算符,默认情况下提供值相等语义。也就是说,当两个记录操作数都为空或者所有字段和自动实现的属性的对应值相等时,两个记录操作数相等。

public class RecordTypesEquality
{
    public record Point(int X, int Y, string Name);
    public record TaggedNumber(int Number, List<string> Tags);

    public static void Main()
    {
        var p1 = new Point(2, 3, "A");
        var p2 = new Point(1, 3, "B");
        var p3 = new Point(2, 3, "A");

        Console.WriteLine(p1 == p2);  // output: False
        Console.WriteLine(p1 == p3);  // output: True

        var n1 = new TaggedNumber(2, new List<string>() { "A" });
        var n2 = new TaggedNumber(2, new List<string>() { "A" });
        Console.WriteLine(n1 == n2);  // output: False
    }
}
Run Code Online (Sandbox Code Playgroud)