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

时间:2017-12-19 10:29:45

标签: 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 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_exception时,结果是异常: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:''Newtonsoft.Json.Linq.JValue'不包含'y'的定义

是Newtonsoft.Json还是其他bug?

2 个答案:

答案 0 :(得分:3)

简短的回答是source.x 'sort of'为空。

要查看此内容,请按以下步骤更改代码:

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 awesome post

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

因此,等效IsNull_yes实施您的现有代码 -  但更接近的是:

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

其行为方式完全相同(即抛出异常)。

答案 1 :(得分:-1)

我的猜测是编译器必须通过查看json字符串source.x?.y来检查@"{ 'x': null }"是否仍然有效。由于编译器必须验证是否存在y,因为' x'是非常有效的非null引用,它会抛出RuntimeBinderException。