我有一个这样定义的泛型方法:

public void MyMethod<T>(T myArgument)

我要做的第一件事是检查myArgument的值是否为该类型的默认值,就像这样:

if (myArgument == default(T))

但这不能编译,因为我不能保证T会实现==运算符。所以我把代码转换成这样:

if (myArgument.Equals(default(T)))

现在这个编译了,但是如果myArgument为null就会失败,这是我测试的一部分。我可以像这样添加一个显式的空检查:

if (myArgument == null || myArgument.Equals(default(T)))

现在我觉得这是多余的。ReSharper甚至建议我将myArgument == null部分更改为myArgument == default(T),这是我开始的地方。有没有更好的方法来解决这个问题?

我需要同时支持引用类型和值类型。


当前回答

这里有个问题

如果你想让它适用于任何类型,default(T)对于引用类型总是空的,对于值类型总是0(或充满0的结构体)。

不过,这可能不是你想要的行为。如果希望以通用方式工作,可能需要使用反射检查T的类型,并处理不同于引用类型的值类型。

或者,您可以在此设置一个接口约束,该接口可以提供一种方法来检查类/结构的默认值。

其他回答

要处理所有类型的T,包括T是基本类型的情况,你需要在两种比较方法中编译:

    T Get<T>(Func<T> createObject)
    {
        T obj = createObject();
        if (obj == null || obj.Equals(default(T)))
            return obj;

        // .. do a bunch of stuff
        return obj;
    }

这个怎么样:

if (object.Equals(myArgument, default(T)))
{
    //...
}

使用static object.Equals()方法可以避免您自己进行空检查。用object显式地限定调用。根据上下文可能没有必要,但我通常用类型名作为静态调用的前缀,只是为了使代码更容易解决。

@ilitirit:

public class Class<T> where T : IComparable
{
    public T Value { get; set; }
    public void MyMethod(T val)
    {
        if (Value == val)
            return;
    }
}

运算符'=='不能应用于'T'和'T'类型的操作数

如果不进行显式空测试,然后调用Equals方法或对象,我想不出有什么方法可以做到这一点。如上所述等于。

您可以使用System设计解决方案。比较,但这最终会导致更多的代码行,并大幅增加复杂性。

为了避免装箱,比较是否相等的泛型的最好方法是使用EqualityComparer<T>. default。这尊重IEquatable<T>(不带装箱)以及object。等于,并处理所有Nullable<T>“解除”的细微差别。因此:

if(EqualityComparer<T>.Default.Equals(obj, default(T))) {
    return obj;
}

这将匹配:

类为空 null(空)对于Nullable<T> 对于其他结构体为0 /false/etc

试试这个:

if (EqualityComparer<T>.Default.Equals(myArgument, default(T)))

它应该编译,并执行您想要的操作。