我如何从c#的泛型方法返回NULL ?

我有一个通用的方法与这个(dummy)代码(是的,我知道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转换为类型参数 因为它可以是一个值类型。 考虑使用'default(T)'代替。"

我能避免这个错误吗?

225771 次浏览
return default(T);

采取错误的建议……和用户default(T)new T

如果您走那条路,您必须在代码中添加一个比较,以确保它是一个有效的匹配。

否则,可能会考虑“匹配已找到”的输出参数。

三个选项:

  • 返回default(或default(T)对于旧版本的c#),这意味着如果T是引用类型(或可空值类型),则返回null0对于int'\0'对于char,等等(默认值表(c#参考))。
  • 如果您愿意使用where T : class约束将T限制为引用类型,然后正常返回null
  • 如果您乐于使用where T : struct约束将T限制为一个非空值类型,那么您可以从一个返回值为T?的方法中正常返回null—注意,这是返回一个空引用,但是可空值类型的空值。

你的另一个选择是在你的声明后面加上这个:

    where T : class
where T: IList

这样它将允许您返回null。

你可以调整你的约束条件:

where T : class

然后返回null是允许的。

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

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

解决方案的软件绝地作品,

你也可以使用一对value和nullable类型来存档:

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. 如果你有对象,那么需要类型转换

    return (T)(object)(employee);
    
  2. if you need to return null.

    return default(T);
    

这里有一个Nullable Enum返回值的工作示例:

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

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

return default(T);

where T : class, IThing
return null;

上述2个答案的另一种选择。如果您将返回类型更改为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
}

为了完整起见,知道你也可以这样做:

return default;

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

因为IThing是接口不可能使用null。因此,必须使用default(T)来确定实际类型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;}}