C# 4 中的 C# 6 nullcheck 扩展

标签 c# c#-4.0 c#-6.0

如何在带有扩展的 C# 4 中实现此功能:

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

where Challenge.Id is string

was given一些扩展:

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 条件运算符返回可为 null 的值。您必须专门为返回可空值的值类型创建一个重载。

这样的事情应该有效:

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)

关于C# 4 中的 C# 6 nullcheck 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34563841/

相关文章:

c# - 在 NetStandard 2.0 类库中使用 Newtonsoft 库

c# - 带返回值的递归函数VS使用OUT参数

winforms - 文本框高度和宽度

linq - 空传播 ?.First() 与 .FirstOrDefault()

c# - 从经典 ASP 迁移到 ASP.Net 的困惑

c# - 在 C# 中使用 Windows 用户名密码

c# - 将二进制读取函数从 C++ 转换为 C#

c# - 使用 LINQ 在 C# 中创建自定义聚合函数

C# 6 安全导航在 VS2015 预览中不起作用

c# - Xamarin Studio c# 空传播运算符