无法将T值1与T值2 = 默认值(default(T))进行比较。为什么?如何在C#上实现比较?

7

我正在尝试以下操作:

T value1 = el.value; // it's of type T already
T value2 = default(T);
if (value1 != value2) // gives the following error: Operator '!=' cannot be applied to operands of type 'T' and 'T'
{
    // ...
}

那么,我如何比较这两个值?为什么会出现这个错误?
提前致谢!

确保T实现了ICompare-ish类型类,并且定义T的方法或类在声明中具有这些引用。 - asawyer
7个回答

13

您可以像Henk提到的那样使用where T : IEquatable<T>的约束条件,或者忽略约束条件并使用:

if (!EqualityComparer<T>.Default.Equals(value1, value2))

我见过这个框架使用那种方法来测试相等性,看起来是一个不错的选择,即使有点啰嗦。 - Joe Enos
我认为这是最简单的方法。谢谢! - Girardi
@Ani:你说得对。我忘记了没有非泛型的IEquatable接口。我会进行编辑。 - Jon Skeet

4

您周围的通用类应列出一个约束:T:IEquatable<T>

然后您必须使用value1.Equals(value2)

所有这些的原因是并非所有类型都定义运算符 ==


1
如果value1为空,您将会得到一个NullReferenceException异常。 - nicodemus13

2
这是什么问题?
if (!value1.Equals(value2))

应该是“跨对象”... :)

2
个人而言,我不喜欢这种不对称的情况。当然,如果value1==null,它会抛出异常。 - CodesInChaos

2
并非所有类型都有默认的==运算符实现。对于类, 默认的==操作是比较引用。而对于结构体,则不存在此类默认实现。
在C#中,您可以为泛型类型参数添加类型约束。不幸的是,您无法定义强制类型具有==运算符实现的约束。最好的做法是强制该类型为类:where T: class有关C#中类型参数约束的文章

1

尝试

Equals(value1, value2)

避免空引用的好方法

1

如果你使用value1.equals(value2),那么在处理null值时会出现问题。更好的方法是:
object.equals(value1,value2)

或者对于引用类型(要小心):
object.referenceEquals(value1,value2)


0

你还可以定义比较运算符(实际上,这里是差异运算符),以便能够比较类型为T的元素。单独使用,编译器不能真正知道你在写value1 != value2时意味着什么,除非先前已经定义了该运算符。

要定义运算符,可以使用

public operator!=(T a, T b) {
    // Comparison code; returns true or false
}

我认为 T 是一个泛型参数,所以这可能是不可能的。 - CodesInChaos

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