简体   繁体   English

空传播运算符和Newtonsoft.Json 10.0.3异常

[英]Null propagation operator and Newtonsoft.Json 10.0.3 exception

I have installed "Newtonsoft.Json" version="10.0.3" 我安装了“Newtonsoft.Json”version =“10.0.3”

and there are two methods: 有两种方法:

    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;
    }

Then I have program: 然后我有程序:

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

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

        Console.ReadLine();
  • When program calls IsNull_yes method then result is "true" 当程序调用IsNull_yes方法时,结果为“true”
  • When program calls IsNull_exception then result is exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'y'' 当程序调用IsNull_exception时,结果是异常:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:''Newtonsoft.Json.Linq.JValue'不包含'y'的定义

Is it Newtonsoft.Json or other bug? 是Newtonsoft.Json还是其他bug?

The short answer is that source.x is 'sort of' null. 简短的回答是source.x'某种' null。

To see this, change the code as following: 要查看此内容,请按以下方式更改代码:

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;
}

You will note that false is written three times, then true . 你会注意到false写了三次,然后是true As such, the equality comparison used by dynamic is not the same as that used by object.Equals etc. See @dbc's awesome post for more details. 因此, dynamic使用的相等比较与object.Equals等使用的相同。 请参阅@ dbc的精彩帖子以获取更多详细信息。

Unfortunately, since it is not really equal, null propagation doesn't kick in (since null propagation does not use the h == null style comparison). 不幸的是,因为它不是真的相等,所以空传播不会起作用(因为空传播不使用h == null样式比较)。

As such the equivalent IsNull_yes implementation is not your existing code - but something closer to: 因此,等效的IsNull_yes实现不是您现有的代码 - 而是更接近于:

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

which acts exactly the same way (ie throws an exception). 其行为方式完全相同(即抛出异常)。

my guess is compiler must be checking if source.x?.y is still valid by looking at json string @"{ 'x': null }" . 我的猜测是编译器必须通过查看json string @"{ 'x': null }"来检查source.x?.y是否仍然有效。 As compiler has to verify if y exists in case 'x' is really valid non-null reference, it throws RuntimeBinderException. 由于编译器必须验证在“x”确实是有效的非空引用的情况下是否存在y,它会抛出RuntimeBinderException。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM