如何从C#中的泛型方法返回NULL?

edo*_*oft 519 c# generics

我有一个通用的方法与这个(虚拟)代码(是的我知道IList有谓词,但我的代码不使用IList但其他一些集合,无论如何这与问题无关...)

static T FindThing<T>(IList collection, int id) where T : IThing, new()
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;  // ERROR: Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead.
}
Run Code Online (Sandbox Code Playgroud)

这给了我一个构建错误

"无法将null转换为类型参数'T',因为它可能是值类型.请考虑使用'default(T)'."

我可以避免这个错误吗?

Jon*_*eet 928

两种选择:

  • 返回default(T)表示null如果T是引用类型(或可空值类型),0for int,'\0'for char等,则返回(默认值表(C#Reference))
  • 将T限制为具有where T : class约束的引用类型,然后null正常返回

  • 我认为这个问题是如果你使用这个泛型方法说,将数据库对象从DbNull转换为Int并返回默认值(T),其中T是一个int,它将返回0.如果这个数字是实际上是有意义的,那么在该字段为空的情况下,您将传递坏数据.或者更好的例子是DateTime.如果该字段类似于"DateClosed"并且它返回为null,因为并且帐户仍处于打开状态,它实际上默认(DateTime)为1/1/0000,这意味着该帐户在计算机发明之前已关闭. (24认同)
  • @Sinaesthetic:所以你要转换为`Nullable <int>`或`Nullable <DateTime>`.如果您使用非可空类型并且需要表示空值,那么您只是在寻找麻烦. (20认同)
  • 如果我的返回类型是枚举而不是类,该怎么办?我不能指定T:enum :( (3认同)
  • 在 .NET 中,枚举是一个围绕整数类型的非常薄(而且相当泄漏)的包装器。约定是对“默认”枚举值使用零。 (2认同)
  • 我同意,我只是想提出来。我认为我一直在做的事情更像是 MyMethod&lt;T&gt;(); 假设它是不可空类型和 MyMethod&lt;T?&gt;(); 假设它是可空类型。所以在我的场景中,我可以使用一个临时变量来捕捉一个空值并从那里开始。 (2认同)

Ric*_*mil 78

return default(T);
Run Code Online (Sandbox Code Playgroud)

  • 我很惊讶这并没有获得更多的支持,因为“default”关键字是一个更全面的解决方案,允许将非引用类型与数字类型和结构结合使用。虽然接受的答案解决了问题(并且确实很有帮助),但它更好地回答了如何将返回类型限制为可为空/引用类型。 (2认同)

The*_*edi 32

你可以调整你的约束:

where T : class
Run Code Online (Sandbox Code Playgroud)

然后返回null是允许的.


Min*_*Min 12

将类约束添加为泛型类型的第一个约束.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()
Run Code Online (Sandbox Code Playgroud)


小智 7

  1. 如果你有对象则需要进行类型转换

    return (T)(object)(employee);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果你需要返回null.

    return default(T);
    
    Run Code Online (Sandbox Code Playgroud)


Jay*_*hil 7

以下是您可以使用的两个选项

return default(T);
Run Code Online (Sandbox Code Playgroud)

要么

where T : class, IThing
 return null;
Run Code Online (Sandbox Code Playgroud)


BFr*_*ree 6

您的另一个选择是将此添加到您的声明的末尾:

    where T : class
    where T: IList
Run Code Online (Sandbox Code Playgroud)

这样它将允许您返回null.


LCI*_*III 6

为了完整起见,很高兴知道您也可以这样做:

return default;
Run Code Online (Sandbox Code Playgroud)

它返回的结果与return default(T);


dev*_*evi 5

TheSoftwareJedi作品的解决方案,

您也可以使用几个值和可为空类型来存档它:

static T? FindThing<T>(IList collection, int id) where T : struct, IThing
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)