67

我正在尝试在 C# 中使用等于 (==) 比较两个结构。我的结构如下:

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();
    }
}

我试图将 struct 作为我的类中的一个属性,并想检查该结构是否等于我试图分配给它的值,然后再继续这样做,所以我没有指示该属性当它没有改变时已经改变,就像这样:

public CisSettings TopCisSettings
{
    get { return _topCisSettings; }
    set
    {
        if (_topCisSettings == value)
        {
            return;
        }
        _topCisSettings = value;
        OnPropertyChanged("TopCisSettings");
    }
}

但是,在我检查是否相等的那一行,我得到了这个错误:

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

我不知道为什么会这样,有人能指出我正确的方向吗?

4

8 回答 8

103

您需要重载==and!=运算符。将此添加到您的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);
}
于 2013-03-04T10:13:51.820 回答
9

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

另请参阅覆盖 Equals() 和运算符 ==CA1815 的指南:覆盖值类型上的等于和运算符等于

于 2013-03-04T10:14:02.473 回答
2

您没有显式实现相等运算符,因此==没有专门为该类型定义。

于 2013-03-04T10:14:17.017 回答
2

你应该重载你的运营商是这样的:

public static bool operator ==(CisSettings a, CisSettings b)
{
    return a.Equals(b);
}
于 2013-03-04T10:15:11.930 回答
2

您需要明确覆盖 operator ==。

public static bool operator ==(CisSettings x, CisSettings y) 
{
   return x.Equals(y);
}

顺便说一句,你最好把比较代码放在public bool Equals(CisSettings other),然后让bool Equals(object obj)调用bool Equals(CisSettings other),这样你就可以通过避免不必要的类型检查来获得一些性能。

于 2013-03-04T10:16:49.263 回答
1

您必须重载“==”运算符,还必须重载“!=”运算符。(看这个注

对于重载运算符,请参阅此页面

于 2013-03-04T10:20:02.640 回答
1

您还可以使用自 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
    }
}
于 2021-12-06T10:01:14.760 回答
0

制作一个方法并将两个stuct obj作为参数一一传递

public Save ReturnGreater(Save online,Save local)
{
    Save DataToSave = new Save();
    DataToSave.Score = local.Score < online.Score ? online.Score : local.Score;
    DataToSave.UnlockGuns = local.UnlockGuns < online.UnlockGuns ? online.UnlockGuns : local.UnlockGuns;
    DataToSave.UnlockLevels = local.UnlockLevels < online.UnlockLevels ? online.UnlockLevels : local.UnlockLevels;
    DataToSave.TotalLevels = local.TotalLevels;
    DataToSave.RemoveAds = local.RemoveAds;
    return DataToSave;
}
于 2021-02-27T13:55:46.013 回答