C#EmptyIfNull扩展,用于任何IEnumerable返回空派生类型

假设nulls和空集合是等价的,我正在尝试为IEnumerable类型编写一个扩展方法,以返回派生类型的空集合而不是null。 这样我就不必在整个地方重复进行空检查,而且我没有得到一个我必须强制转换的IEnumerable。

例如

List MethodReturningFooList() { ... } Foo[] MethodReturningFooArray() { ... } void Bar() { List list = MethodReturningFooList().EmptyIfNull(); Foo[] arr = MethodReturningFooArray().EmptyIfNull(); } public static class Extension { public static T EmptyIfNull(this T iEnumerable) where T : IEnumerable, new() { var newTypeFunc = Expression.Lambda<Func>(Expression.New(typeof(T))).Compile(); return iEnumerable == null ? newTypeFunc() : iEnumerable; } } 

这个扩展似乎有效,但是有人看到任何陷阱吗?

是的,在这种情况下会破坏:

 IEnumerable test = null; var result = test.EmptyIfNull(); 

你可以像这样解决它:

 public static class Extension { public static List EmptyIfNull(this List list) { return list ?? new List(); } public static T[] EmptyIfNull(this T[] arr) { return arr ?? new T[0]; } public static IEnumerable EmptyIfNull(this IEnumerable enumerable) { return enumerable ?? Enumerable.Empty(); } } 

您需要重载以确保返回相同的集合类型(与以前一样)。

这是一个通过返回相同的集合类型无法工作的案例:

 public abstract class MyAbstractClass : IEnumerable { private List tempList = new List(); public IEnumerator GetEnumerator() { return tempList.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return tempList.GetEnumerator(); } } MyAbstractClass myClass = null; MyAbstractClass instance = myClass.EmptyIfNull(); 

在不知道子类的情况下,我们无法在这里返回MyAbstractClass 。 并且使用空引用,没有猜测就不可能。 此外,当类没有默认构造函数时会发生什么? 进入危险的领域。

您需要拥有一个全能的IEnumerable返回,并让用户强制转换它,或者提供重载,如上所示

我应该这样改进

 public static class Extension { public static IEnumerable EmptyIfNull(this IEnumerable iEnumerable) { return iEnumerable ?? Enumerable.Empty(); } } 

或者更好的C#6

 public static class Extension { public static IEnumerable EmptyIfNull(this IEnumerable iEnumerable) => iEnumerable ?? Enumerable.Empty(); } 

我得到一个generics参数的方法(由于我将创建一个这种类型的实例,因此限制为一个类)。 然后我在运行时定义一个默认对象,并检查参数接收的对象是否为null,如果对象为null,则返回在运行时实例化的对象,否则返回通过参数传递的对象本身。

我希望有所帮助

  public static T EmptyIfNull(this T obj) where T : class { var objNotNull = Activator.CreateInstance(typeof(T)); if (obj == null) return objNotNull as T; return obj; } 

unit testing :

在此处输入图像描述