如何在C#的通用方法中返回NULL?

658
我有一个通用方法,其代码如下(是的,我知道IList有谓词,但我的代码不使用IList而是一些其他集合,无论如何,这与问题无关...)
    static T FindThing<T>(IList collection, int id) where T : IThing, new()
    {
        foreach (T thing in collection)
        {
            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.
    }

我遇到了一个构建错误

"不能将null转换为类型参数'T',因为它可能是值类型。考虑使用'default(T)'代替。"

我能避免这个错误吗?


在C# 8中,可空引用类型是否是更好的解决方案?https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references 不管TObject还是intchar,都返回null - Alexander
很遗憾,签名中的 T? 无法工作。@Alexander-ReinstateMonica 我已经阅读了文章,但无论是引用类型还是值类型,我都找不到返回 null 的方法。 - mireazma
1
@mireazma 这个信息太少了,我无法提供帮助。您应该开一个新问题。 - Alexander
我看到的主要问题是你试图使用 null 作为某些地方出现问题的指示。我建议改为抛出异常。这就是异常存在的原因,你可以省略在每个地方编写 if (... != null) 的步骤。 - Markus Safar
13个回答

3
由于IThing是接口,无法使用null。因此,在调用函数之前,您必须使用default(T)确定实际类型T的默认值,该类型在函数定义之前已定义。
using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        
        IThing x = new List<Thing>().FindThing(1);
        
    }

}

public static class Ext {
    public static T FindThing<T>(this IList<T> collection, int id) where T : IThing, new()
    {
        foreach (T thing in collection)
        {
            if (thing.Id == id) return (T)thing;
        }
    
        //return null; //not work
        //return (T)null; //not work
        //return null as T; //not work
        return default(T); //work
    }
}

public interface IThing { int Id {get; set;} }
public class Thing : IThing { public int Id {get;set;}}

你试过这段代码吗?只有 return default(T); 可以正常工作。 - E. Shcherbo
@E.Shcherbo 不,它可以工作。在 fiddle 上尝试一下。 - Mertuarez
好的,我没有在你的回答中注意到你的 IThing 是类,所以你的方法知道 T 是类,但我相信问题的作者的意思是 IThing 是一个接口(I 前缀表示的是这个意思)。 - E. Shcherbo
@E.Shcherbo 我必须道歉,你是正确的。不幸的是,问题没有很详细的描述,因此对于像我这样的懒人来说,达到相同的条件并不是很可行。 :D - Mertuarez
没关系,尽管你的回答是关于另一个概念(类与接口),但我仍然认为它很好。它展示了一个重要的观点,即当类型参数已知为类或接口时,通用方法的行为如何不同,并强调了 where T : IThing 也适用于值类型。 - E. Shcherbo

3

采用错误的建议...要么使用default(T),要么使用new T

如果你选择这条路,你需要在你的代码中添加一个比较来确保它是一个有效的匹配。

否则,可以考虑将"match found"作为输出参数。


0

另一种替代上面提出的两个答案的方法。如果您将返回类型更改为object,则可以返回null,同时转换非空返回。

static object FindThing<T>(IList collection, int id)
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return (T) thing;
    }
    return null;  // allowed now
}

缺点:这将要求方法的调用者对返回的对象进行强制转换(在非空情况下),这意味着装箱->性能较差。我是对的吗? - Csharpest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接