簡體   English   中英

C#EmptyIfNull擴展,用於任何IEnumerable返回空派生類型

[英]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>();
}

我得到一個泛型參數的方法(由於我將創建一個這種類型的實例,因此限制為一個類)。 然后我在運行時定義一個默認對象,並檢查參數接收的對象是否為null,如果對象為null,則返回在運行時實例化的對象,否則返回通過參數傳遞的對象本身。

我希望有所幫助

    public static T EmptyIfNull<T>(this T obj) where T : class
    {           
        var objNotNull = Activator.CreateInstance(typeof(T));

        if (obj == null)
            return objNotNull as T;

        return obj;
    }

單元測試 :

在此輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM