【问题标题】:Tuple == Confusion元组 == 混乱
【发布时间】:2012-03-22 16:39:47
【问题描述】:

假设我定义了两个元组:

Tuple<float, float, float, float> tuple1 = new Tuple<float, float, float, float>(1.0f, 2.0f, 3.0f, 4.0f);
Tuple<float, float, float, float> tuple2 = new Tuple<float, float, float, float>(1.0f, 2.0f, 3.0f, 4.0f);

如果我尝试比较元组,我会得到不同的结果

bool result1 = (tuple1 == tuple2);    // FALSE
bool result2 = tuple1.Equals(tuple2); // TRUE

我希望这两个调用都返回 true。 == 到底在比较什么?

【问题讨论】:

标签: c# .net tuples equality


【解决方案1】:

对于元组,== 正在比较对象引用,因为它不会重载 == 运算符。由于对象是等价的,但具体实例不同,Equals() 返回true== 返回false

许多类型不会重载==,有些类型更喜欢区分Equals() 用于等价和== 用于引用相等。

此外,依赖== 进行等效可能会导致一些奇怪:

public bool AreSame<T>(T first, T second) where T : class
{
    return first == second;
}

上面的代码将始终检查引用相等性,因为不受约束的泛型在编译时被视为object,因此如果方法不是虚拟的,您将获得对象的版本(即使类型,例如@987654333 @重载==)。

因此上述代码的这种用法:

var x = "Hello";
var y = "H";

// doing concat to avoid string interring
AreSame(x, y+"ello");

是的,字符串是等价的,是的 Tstring,但是 == 绑定到对象的 == 因为泛型是不受约束的,因此即使相同的代码与显式的string 参数将返回true

【讨论】:

  • 谢谢 我以为==Equals 本质上是一样的。我的困惑来自 MSDN 的重载指南 msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx,其中 == 不仅检查引用相等性。
  • 最好的经验法则是检查类的文档,看看它们是否实现了 operator==,即使这样,我更喜欢使用 Equals() 进行等价检查,因为那样的话很明显,您正在寻找等效检查。但这就是我。
  • AFAICT,AreSame 甚至无法编译。我从编译器收到以下错误:“运算符'=='不能应用于'T'和'T'类型的操作数”
  • 对不起,你得说 where T : class,因为 class 的 == 和 struct 的 == 是两种不同的鸟...
【解决方案2】:

== 正在比较对象引用。 Tuple 类没有重载== 运算符,所以需要使用.Equals

【讨论】:

  • 重写 == 运算符不是最佳实践吗?我假设所有 .NET 类都覆盖了 == 运算符。
  • 由于Tuple 是不可变的,似乎可以提出一个合理的论点,即此类将成为重载运算符的良好候选者。但是,根据我的经验,我唯一期望这种重载的类是 string 或其他准原始类型,例如 DateTimeTimeSpan 等。
【解决方案3】:

== for Tuple 只会看到引用,因此您会看到它是错误的。

PS:推荐的方法是:

var tuple1 = Tuple.Create(1.0f, 2.0f, 3.0f, 4.0f)

【讨论】:

  • 谢天谢地 n +1 .0f,没有它,编译器一直在尖叫 double to float conversion 错误...
  • 加上f后,可以去掉.0,即1f2f
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多