C#EmptyIfNull扩展,用于任何IEnumerable返回空派生类型 [英] C# EmptyIfNull extension for any IEnumerable to return empty derived type
问题描述
假设null和空集合是等效的,我正在尝试为IEnumerable类型编写扩展方法,以返回派生类型的空集合而不是null.这样一来,我不必在整个地方重复执行null检查,也不会得到必须强制转换的IEnumerable.
Assuming nulls and empty collections are equivalent, I'm trying to write an extension method for IEnumerable types to return empty collections of the derived type instead of null. This way I don't have to repeat null checks all over the place, and I don't get an IEnumerable back that I have to cast.
例如
List<Foo> MethodReturningFooList()
{
...
}
Foo[] MethodReturningFooArray()
{
...
}
void Bar()
{
List<Foo> list = MethodReturningFooList().EmptyIfNull();
Foo[] arr = MethodReturningFooArray().EmptyIfNull();
}
public static class Extension
{
public static T EmptyIfNull<T>(this T iEnumerable)
where T : IEnumerable, new()
{
var newTypeFunc = Expression.Lambda<Func<T>>(Expression.New(typeof(T))).Compile();
return iEnumerable == null ? newTypeFunc() : iEnumerable;
}
}
此扩展程序似乎有效,但是有人看到陷阱吗?
This extension seems to work, but does anyone see any pitfalls?
推荐答案
是的,在这种情况下会中断:
Yes, it will break in this case:
IEnumerable<int> test = null;
var result = test.EmptyIfNull();
您可以这样解决:
public static class Extension
{
public static List<T> EmptyIfNull<T>(this List<T> list)
{
return list ?? new List<T>();
}
public static T[] EmptyIfNull<T>(this T[] arr)
{
return arr ?? new T[0];
}
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> enumerable)
{
return enumerable ?? Enumerable.Empty<T>();
}
}
您将需要重载以确保您返回的集合类型与以前一样.
You'll need overloads to make sure you're returning the same collection type (as you were before).
以下是无法通过返回相同的集合类型进行工作的情况的示例:
Here's an example of a case that can't work by returning the same collection type:
public abstract class MyAbstractClass : IEnumerable<int>
{
private List<int> tempList = new List<int>();
public IEnumerator GetEnumerator()
{
return tempList.GetEnumerator();
}
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
return tempList.GetEnumerator();
}
}
MyAbstractClass myClass = null;
MyAbstractClass instance = myClass.EmptyIfNull();
在不了解子类的情况下,我们无法在这里返回 MyAbstractClass
.对于空引用,如果没有猜测就不可能做到这一点.此外,当类没有默认构造函数时会发生什么?进入危险区域.
There's no way we can return a MyAbstractClass
here without knowing about subclasses. And with a null reference, that's not possible without guessing. Further, what happens when classes do not have a default constructor? Getting into dangerous territory.
您需要要么获得一个全面的 IEnumerable< T>
返回,然后让用户转换它,要么如上所述提供重载
You'll need to either have a catch-all IEnumerable<T>
return, and have the user cast it, or provide overloads as I've shown above
这篇关于C#EmptyIfNull扩展,用于任何IEnumerable返回空派生类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!