泛型函数:返回一个非空值

本文关键字:一个 空值 函数 返回 泛型 | 更新日期: 2023-09-27 18:06:20

我写了这个简单的实用函数:

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

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

类型'T'必须是一个非空值类型,以便在泛型类型或方法'System.Nullable

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

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

代替:

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

我觉得我遗漏了一些c#的基本知识。是否存在一种方法来完成我的任务?

泛型函数:返回一个非空值

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

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

public static T IsNull<T>(T? v, T d) where T : struct
{
    return v == null ? d : v.Value;
}
然而,另一个答案确实正确地指出,在这种特定的情况下,您可以选择使用空合并运算符??

这被称为空合并,并且有一个内置的操作符来完成它:

int myValue = record.myField ?? 0

虽然其他答案都很好,但您可能希望编写的方法可以同时使用引用和值类型。您可以通过两个重载来实现这一点,这两个重载都带有泛型约束。

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;
}

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

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