从泛型方法返回null

时间:2011-03-07 20:18:07

标签: c# .net

如何从泛型方法返回null值?

protected T ValueOrDefault<T>(IDataReader reader, int ordinalId)
        {  
  Type t = typeof(reader.GetValue(ordinalId));
    if (t.IsValueType){
        //Struct. How do I return null?
    } else { 
        //Class
        //just return  null
        return  default(T);
    }
}

8 个答案:

答案 0 :(得分:11)

default(T)适用于这两种情况。

答案 1 :(得分:4)

default(T)在两种情况下都起作用,但其含义与值类型略有不同。它确实返回该类型的默认值。对于Method<int>,它将返回0,而不是null

更新:鉴于您的方法签名:

protected T ValueOrDefault<T>(IDataReader reader, int ordinalId)

在值类型的情况下,您不能返回Nullable<T>,如果是引用类型,则不能输入T。那必须是两种不同的方法。

答案 2 :(得分:2)

显然,如果返回类型为null或引用类型,则只能返回Nullable<T>。正常值类型没有null

对于引用类型default(T)null,对于Nullable<T>,它也为null。因此,在default(T)存在的两种情况下,您都可以使用null

如果类型是另一个值类型default(T)将不是null,但是因为没有null无论如何都没有意义。


如果T是引用类型/ TNullable<T>用于普通值类型,则不可能简单地使用返回类型为T?的方法。< / p>

可以尝试定义类似的东西,但它不会编译,因为编译器不理解通用约束是互斥的。它只是不考虑通用约束。

T? a<T>()
  where T:struct
{
}

T a<T>()
  where T:class
{
}

您需要以其他方式使这些方法不同。通过使用不同的名称或不同的参数。

答案 3 :(得分:2)

如果要返回T?,如果它是值类型,则必须使用两种不同的方法。但是,存在一种复杂性,因为方法不能仅仅通过它们的返回类型而有所不同(围绕通用args的问题也不是方法签名的一部分)。因此,您必须提供一个“stub”方法参数,编译器使用该参数来解析要调用的方法:

public T MyMethod<T>(T stub) where T : class {
    // ...
    return null;
}

public T? MyMethod<T>(T? stub) where T : struct {
    // ...
    return null;
}

// this will then compile...
string s = MyMethod<string>(null);
int? i = MyMethod<int>(null);

答案 4 :(得分:1)

为无约束null值返回T是不合法的。例如,考虑将T实例化为值类型。在这种情况下,null将不是合法值,因此代码是非法的。

您正在寻找的是default(T)。这适用于值和引用类型。对于引用类型,它将生成null,对于值类型,它将生成零初始化值。

答案 5 :(得分:1)

在 C# 9 中,可以让单个方法为引用和可空值类型返回 null。注意字符串和字符串?是完全相同的类型,但 int 和 int?不同(Int32 和 Nullable)。

[TestMethod]
public void TestGenericNull()
{
  static T? GetDefault<T>(bool wantNullable) => wantNullable ? default(T?) : default(T);

  string? s1 = GetDefault<string>(false);
  Assert.IsNull(s1);
  string? s2 = GetDefault<string>(true);
  Assert.IsNull(s2);

  int? d1 = default(int);
  Assert.AreEqual(d1, 0);
  int? d2 = default(int?);
  Assert.IsNull(d2);

  int? n1 = GetDefault<int>(false);
  Assert.AreEqual(n1, 0);
  int? n2 = GetDefault<int>(true);
  Assert.AreEqual(n2, 0); // Expected default(int?), i.e. Nullable<int> with no value.

  int? n4 = GetDefault<int?>(false);
  Assert.IsNull(n4);
  int? n5 = GetDefault<int?>(true);
  Assert.IsNull(n5);
}

答案 6 :(得分:0)

要了解无法解决的原因,请尝试使用值类型替换T

protected int ValueOrDefault<int>(IDataReader reader, int ordinalId)
        {  
  Type t = typeof(reader.GetValue(ordinalId));
    if (t.IsValueType){
        //Struct. How do I return null?
    } else { 
        //Class
        //just return  null
        return  default(int);
    }
}

如果返回类型为int,则无法返回null,因为它不是有效值。 T的类型首先必须是可空的,在这种情况下default(T)可以工作。

答案 7 :(得分:0)

您只能使用return default,最后不带(T)。 C#7.1或更高版本。