1

我写了这个微不足道的效用函数:

public static T isNull<T>(T? v, T d)
{
    return v == null ? d : v.Value;
}

目的是避免烦人的任务,例如检查成员是否为空,这在读取 linq 记录集时很常见。问题是它抛出了这个错误:

类型“T”必须是不可为空的值类型,才能将其用作泛型类型或方法“System.Nullable<T>”中的参数“T”

这个错误似乎是合法的,无论如何我希望我能做这样的事情:

int? myField = record.myField;
int  myValue = isNull(myField, 0);

代替:

int? myField = record.myField;
int  myValue = myField == null ? 0 : myField.Value;

我觉得我缺少一些 c# 基础知识。是否存在完成我的任务的方法?

4

3 回答 3

6

泛型约束可用于泛型函数以将允许使用的类型限制为某些子集,这为您如何在方法或类中使用这些类型提供了可能性。

在这种情况下,您可以应用约束以将T其限制为 astruct以解决您的特定编译器错误。

public static T IsNull<T>(T? v, T d) where T : struct
{
    return v == null ? d : v.Value;
}

但是,另一个答案确实正确指出您可以选择??在这种特殊情况下使用空合并运算符。

于 2013-03-29T01:48:40.427 回答
4

这称为空值合并,并且有一个内置运算符来执行此操作:

int myValue = record.myField ?? 0
于 2013-03-29T01:52:14.243 回答
3

虽然其他答案都很好,但大概您想编写您的方法,以便它适用于引用和值类型。您可以通过使用两个具有通用约束的重载来实现这一点。

public static T IsNull<T>(T v, T d) where T : class
{
    return v ?? d;
}

public static T IsNull<T>(T? v, T d) where T : struct
{
    return v.HasValue ? v.Value : d;
}

注意:IsNull使用值类型以外的调用Nullable<T>仍然无法编译。例如

string myString = ...
Console.WriteLine(IsNull(myString, "foo"))            // works

object myObject = ...
Console.WriteLine(IsNull(myMyObject, new object()))   // works

DateTime? myDateTime = ...
Console.WriteLine(IsNull(myDateTme, DateTme.Now))     // works

int? myInt1 = ...
Console.WriteLine(IsNull(myInt1, DateTme.Now))        // works

int myInt2 = ...
Console.WriteLine(IsNull(myInt2, DateTme.Now))        // <-- compiler error
于 2013-03-29T02:03:41.460 回答