如何最优地使用C#结构体作为字典的键?

7

我有一个C#结构体,它用作标准字典集合中的键。我已经重写了它的GetHashCode和Equals方法,但是我对Equals方法被赋予一个装箱对象而不是直接引用我的结构体类型感到有点不满意。

有什么方法可以优化我的结构体类型在使用字典时避免不必要的装箱操作吗?

(这不是过早的优化,而是完全适当的优化,非常感谢。)


https://dev59.com/dWYr5IYBdhLWcg3w8-rA - user6144226
2个回答

9

您可以实现一个通用的比较器:

public class MyStructComparer : IEqualityComparer<MyStruct>
{
    public bool Equals(MyStruct x, MyStruct y)
    {
        // ...
    }
    public int GetHashCode(MyStruct obj)
    {
        // ...
    }
}

然后将其用于字典构造器

var myStructDict = new Dictionary<MyStruct, string>(new MyStructComparer());

另一种方法是在 MyStruct 中实现 IEquatable<MyStruct>,例如:

public struct MyStruct: IEquatable<MyStruct>
{
    public int Id;

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        return obj is MyStruct && Equals((MyStruct)obj);
    }

    public bool Equals(MyStruct other)
    {
        return this.Id == other.Id;
    }

    public override int GetHashCode()
    {
        return this.Id;
    }
}

然后可以使用默认构造函数初始化字典:
var myStructDict = new Dictionary<MyStruct, string>();

看起来完美!在我的主循环开始之前,只需要一个对象构造的代价和那个烦人的循环内装箱操作就消失了。我会看看在分析器中它的表现如何。 - billpg
2
@billpg:你也可以实现 IEquatable<MyStruct> 接口。我已经相应地编辑了我的答案。 - Tim Schmelter

0
你也可以尝试运算符重载。 请查看下面的代码。
struct MyStruct
    {
        public int id;

        public static bool operator ==(MyStruct s1, MyStruct s2)
        {
            if (s1.id == s2.id)
                return true;
            return false;
        }

        public static bool operator !=(MyStruct s1, MyStruct s2)
        {
            if (s1.id == s2.id)
                return false;
            return true;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            return obj is MyStruct && Equals((MyStruct)obj);
        }

        public bool Equals(MyStruct other)
        {
            return this.id == other.id;
        }

        public override int GetHashCode()
        {
            return this.id;
        }
    }

1
根据参考来源,字典中从不使用运算符==/!=进行比较。 - user6144226

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接