C# 4 中的 C# 6 nullcheck 扩展

C# 6 nullcheck extensions in C# 4

如何使用扩展在 C# 4 中实现:

string challengeId;
if(challengeId == mViewModel?.Challenge?.Id)

where Challenge.Id is string

一些分机:

public static TValue GetOrDefault<TObject, TValue>(this TObject obj, Func<TObject, TValue> getter, TValue defaultValue = default(TValue))
            where TObject : class
        {
            return obj == null ? defaultValue : getter(obj);
        }

那我就可以这样用了:

string challengeId;
if(challengeId == mViewModel.GetOrDefault(x => x.Challeng).GetOrDefault(x => x.Id)

所有组合都可以。如果 ID 不是 string 并且我们想比较 int 怎么办?

int challengeId;
    if(challengeId == mViewModel.GetOrDefault(x => x.Challeng).GetOrDefault(x => x.Id)

where Challenge.Id is int

对于值类型,null 条件运算符 returns 可为空。您必须专门为 returns 可为空的值类型创建重载。

像这样的东西应该可以工作:

public static TValue? GetOrDefault<TObject, TValue>(this TObject obj, Func<TObject, TValue> getter, TValue? defaultValue = default(TValue?))
    where TObject : class
    where TValue : struct
{
    return obj == null ? defaultValue : getter(obj);
}

您可能需要更改名称或其他内容,因为编译器可能会发现该方法与其他重载不明确。编译器将不知道使用哪个重载,因为它们的使用方式不容易区分。

例如:

mViewModel.GetOrDefault(x => x.Challenge).GetOrDefault(x => x.Id)

第二次使用会产生歧义,因为编译器不清楚重载的目的是什么。通用约束不足以解决过载问题。

您将不得不通过指定足够的参数让编译器可以推断哪个是正确的,指定类型参数,或者按照我之前的建议,更改方法的名称来明确使用哪个重载。

mViewModel.GetOrDefault(x => x.Challenge).GetOrDefault(x => x.Id, default(int?))

mViewModel.GetOrDefault(x => x.Challenge).GetOrDefault<Challenge, int>(x => x.Id)

mViewModel.GetReferenceOrDefault(x => x.Challenge).GetValueOrDefault(x => x.Id)