[英]C# EmptyIfNull extension for any IEnumerable to return empty derived type
假設nulls和空集合是等價的,我正在嘗試為IEnumerable類型編寫一個擴展方法,以返回派生類型的空集合而不是null。 這樣我就不必在整個地方重復進行空檢查,而且我沒有得到一個我必須強制轉換的IEnumerable。
例如
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;
}
}
這個擴展似乎有效,但有沒有人看到任何陷阱?
是的,在這種情況下會破壞:
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>();
}
}
您需要重載以確保返回相同的集合類型(與以前一樣)。
這是一個通過返回相同的集合類型無法工作的案例:
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
。 並且使用空引用,沒有猜測就不可能。 此外,當類沒有默認構造函數時會發生什么? 進入危險的領域。
你需要有一個全能的IEnumerable<T>
返回,並讓用戶強制轉換,或提供重載,如上所示
我應該這樣改進
public static class Extension
{
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> iEnumerable)
{
return iEnumerable ?? Enumerable.Empty<T>();
}
}
或者更好的C#6
public static class Extension
{
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> iEnumerable)
=> iEnumerable ?? Enumerable.Empty<T>();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.