C#EmptyIfNull扩展,用于任何IEnumerable返回空派生类型 [英] C# EmptyIfNull extension for any IEnumerable to return empty derived type

查看:104
本文介绍了C#EmptyIfNull扩展,用于任何IEnumerable返回空派生类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆