Elvis(?.)C#5.0中的扩展方法

N.D*_*D.B 11 c# extension-methods

是否可以在C#5.0中创建一些扩展方法,以提供与C#6.0 Elvis(?.)运算符相同的结果?

例如:

//C# 6.0 way
var g1 = parent?.child?.child?.child; 
if (g1 != null) // TODO

//C# 5.0 way
var g1 =   parent.elvisExtension().child.elvisExtension().child.elvisExtension().child; 
if (g1 != null) // TODO
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 9

有可能使用与mocking相同的方法(parent它不会返回,而是返回父级的'mock',它将返回null或对象值).但是,这有点复杂.

这非常简单,并且可以使用基本功能:

public static class Helper
{
    public static TReturnType Elvis<TOnType, TReturnType>(this TOnType onObj, Func<TOnType, TReturnType> selector)
        where TReturnType : class
    {
        if (onObj == null)
            return null;
        return selector(onObj);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试它:

var person = new Person { Parent = new Person { Parent = new Person() } };
var result = person.Elvis(p => p.Parent).Elvis(p => p.Parent);
Run Code Online (Sandbox Code Playgroud)

正确获取Person对象.

person = new Person();
result = person.Elvis(p => p.Parent).Elvis(p => p.Parent);
Run Code Online (Sandbox Code Playgroud)

返回null.

但是,这仅适用于可空类型.不幸的是,你不能创建一个重载where TReturnType : struct,我们需要一个新的方法来处理它.

因此,对于非可空类型,我们需要这样:

public static TReturnType? Elviss<TOnType, TReturnType>(this TOnType onObj, Func<TOnType, TReturnType> selector)
    where TReturnType : struct
{
    if (onObj == null)
        return default(Nullable<TReturnType>);
    return selector(onObj);
}
Run Code Online (Sandbox Code Playgroud)

并测试它:

var result = person.Elvis(p => p.Parent).Elviss(p => p.Id);
Run Code Online (Sandbox Code Playgroud)