如何从泛型方法返回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);
}
}
答案 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
是引用类型/ T
而Nullable<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或更高版本。