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

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),这是我开始的地方。有没有更好的方法来解决这个问题?

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


当前回答

@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设计解决方案。比较,但这最终会导致更多的代码行,并大幅增加复杂性。

其他回答

试试这个:

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

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

不知道这是否适用于您的需求,但您可以将T约束为实现IComparable等接口的类型,然后从该接口(IIRC支持/处理空值)使用ComparesTo()方法,如下所示:

public void MyMethod<T>(T myArgument) where T : IComparable
...
if (0 == myArgument.ComparesTo(default(T)))

你可能还可以使用其他接口,比如IEquitable等等。

我觉得你很接近了。

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

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

您只需要反向调用等号的对象,就可以实现一种优雅的零安全方法。

default(T).Equals(myArgument);

要处理所有类型的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;
    }

基于公认答案的扩展方法。

   public static bool IsDefault<T>(this T inObj)
   {
       return EqualityComparer<T>.Default.Equals(inObj, default);
   }

用法:

   private bool SomeMethod(){
       var tValue = GetMyObject<MyObjectType>();
       if (tValue == null || tValue.IsDefault()) return false;
   }

替换null来简化:

   public static bool IsNullOrDefault<T>(this T inObj)
   {
       if (inObj == null) return true;
       return EqualityComparer<T>.Default.Equals(inObj, default);
   }

用法:

   private bool SomeMethod(){
       var tValue = GetMyObject<MyObjectType>();
       if (tValue.IsNullOrDefault()) return false;
   }