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 :