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

How can I return NULL from a generic method in C#?

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

1
2
3
4
5
6
7
8
9
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.
}

这会导致生成错误

"Cannot convert null to type parameter
'T' because it could be a value type.
Consider using 'default(T)' instead."

我能避免这个错误吗?


两种选择:

  • 返回default(T),即如果t为引用类型(或可空值类型),则返回null0int'\0'char等(默认值表(c reference))。
  • 将t限制为具有where T : class约束的引用类型,然后将null作为正常值返回


1
return default(T);


您只需调整约束:

1
where T : class

则允许返回空值。


将类约束作为第一个约束添加到泛型类型。

1
static T FindThing<T>(IList collection, int id) where T : class, IThing, new()


  • 如果有对象,则需要进行类型转换

    1
    return (T)(object)(employee);
  • 如果需要返回空值。

    1
    return default(T);

  • 你的另一个选择是在你的声明末尾加上这个:

    1
    2
        where T : class
        where T: IList

    这样它将允许您返回空值。


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

    1
    return default(T);

    1
    2
    where T : class, IThing
     return null;

    软件工程的解决方案,

    此外,您还可以使用两种值类型和可以为空的类型将其存档:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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;
    }

    下面是一个可为空的枚举返回值的工作示例:

    1
    2
    3
    4
    public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct
    {
        return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value);
    }

    接受错误的建议…以及用户default(T)new T

    您必须在代码中添加一个比较,以确保在执行该路径时它是有效的匹配项。

    否则,可能会考虑"match found"的输出参数。


    上述2个答案的另一个备选方案。如果将返回类型更改为object,则可以返回null,同时强制转换非空返回。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    static object FindThing<T>(IList collection, int id)
    {
        foreach T thing in collecion
        {
            if (thing.Id == id)
                return (T) thing;
        }
        return null;  // allowed now
    }