【发布时间】:2010-09-06 08:05:45
【问题描述】:
这有效吗?
public struct MyStruct
{
public int Foo { get; set; }
public static bool operator ==(MyStruct a, MyStruct b)
{
return a.Equals(b);
}
public static bool operator !=(MyStruct a, MyStruct b)
{
return !a.Equals(b);
}
}
(我知道这有点低效,因为 Object.Equals 默认对值类型使用反射。但它有效吗?)
我之所以问是因为 ReSharper 会突出显示它并警告我 MyStruct defines operator '==' or operator '!=' but does not provide 'Object.Equals(object o)' and 'Object.GetHashCode()'。
【问题讨论】:
-
警告是因为 Damien 所说的:它违背了开发人员的期望。
-
恕我直言 Foo { get;放;设置器有点奇怪。值类型应该是不可变的,setter 只会在一个非常复杂的(无用的)更新网络中欺骗你。如果结构中的单个值发生变化,只需创建一个完整的新结构。例如:一个点是一个结构。而且您不能更改点的 X 或 Y。因为点是“静态”实体,所以不能“移动”它们。如果一个点发生变化,它必须是另一个点,即一个新的结构。结论:将所有属性设为只读并仅通过构造函数传递值。
-
Caspar:人们一直这么说,但我强烈反对。如果我将 setter 设为私有,struct Point 的用户只需将他们的
p.X++;更改为可读性较差的p = new Point(p.X + 1, p.Y);,或者像p = p.WithX(p.X + 1);这样的奇怪东西,根本没有任何好处。 -
不可变值类型的好处不仅仅是语法相关。这是因为它们比可变值类型更容易推理。 Eric Lippert 可能比任何人都能更好地解释这一点 - blogs.msdn.com/b/ericlippert/archive/2008/05/14/…。但是,如果您意识到这些弊端,并且将来与您的可变值类型交互的每个人都可以接受,那就去做吧。
-
@Alex Humphrey:可变值类型很好,只要它们永远不会改变“this”,也就是说,改变它们的唯一方法是通过公共可变字段或通过修改的公共方法通过引用传递的结构。 .net 对它们的处理存在一些限制(尤其是属性),但可以通过定义一个包含 T 类型的单个公共字段的 Holder
类来克服这些限制。
标签: c# .net operator-overloading equals equals-operator