C# Null传播运算符和Newtonsoft.Json 10.0.3异常

C# Null传播运算符和Newtonsoft.Json 10.0.3异常,c#,json.net,C#,Json.net,我已经安装了“Newtonsoft.Json”version=“10.0.3” 有两种方法: public static bool IsNull_yes(dynamic source) { if (source.x == null || source.x.y == null) return true; return false; } public static bool IsNull_exception(dynamic sourc

我已经安装了“Newtonsoft.Json”version=“10.0.3”

有两种方法:

    public static bool IsNull_yes(dynamic source)
    {
        if (source.x == null || source.x.y == null) return true;
        return false;
    }

    public static bool IsNull_exception(dynamic source)
    {
        if (source.x?.y == null) return true;
        return false;
    }
然后我有一个程序:

        var o = JObject.Parse(@"{  'x': null }");

        if (IsNull_yes(o) && IsNull_exception(o)) Console.WriteLine("OK");

        Console.ReadLine();
  • 当程序调用IsNull_yes方法时,结果为“true”
  • 当程序调用IsNull\U异常时,结果是异常: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:“Newtonsoft.Json.Linq.JValue”不包含“y”的定义

是Newtonsoft.Json还是其他bug?

我猜编译器必须通过查看Json字符串
@“{x':null}”来检查
source.x?.y
是否仍然有效。由于编译器必须在“x”确实是有效的非空引用的情况下验证y是否存在,它会抛出RuntimeBinderException。

简单的回答是
source.x
为空

要查看此信息,请按以下方式更改代码:

public static bool IsNull_exception(dynamic source)
{
    var h = source.x;  
    Console.WriteLine(object.ReferenceEquals(null, h));   // false
    Console.WriteLine(null == h);                         // false  
    Console.WriteLine(object.Equals(h, null));            // false
    Console.WriteLine(h == null);                         // true

    if (source.x?.y == null) return true;
    return false;
}
您将注意到
false
被写入三次,然后
true
。因此,
dynamic
使用的相等比较与
object.Equals
等使用的相等比较不同。有关更多详细信息,请参阅@dbc's

不幸的是,由于它不是真正的相等,因此空传播不会生效(因为空传播不使用
h==null
样式比较)

因此,等效的
IsNull\u yes
实现是而不是您现有的代码- 但更接近于:

public static bool IsNull_yes(dynamic source)
{
    if (null == source.x || source.x.y == null) return true;
    return false;
}

其行为方式完全相同(即引发异常)。

Y未定义为什么在source.x==null时选中“Y”?在IsNull_yes方法中,我们有相同的方法:我们检查第一部分,当它为真时,我们不检查逻辑表达式中的另一部分。差异在哪里?将ISNullException中的source.x?.y更改为source.x。如果我将source.x?.y更改为source.x,我将获得与IsNull相同的方法。是的,但问题是关于C的行为:为什么C#null传播运算符与smt的工作方式不同null?使用dotPeek表明,与在强类型上使用
?。
运算符相比,在动态上使用
?。
运算符会导致。有很多例子表明Elvis操作符不能很好地处理动态。如果是在运行时,我很困惑为什么会涉及编译器?