为啥 DataMemberAttribute 需要对布尔属性进行特殊处理

Posted

技术标签:

【中文标题】为啥 DataMemberAttribute 需要对布尔属性进行特殊处理【英文标题】:Why Does the DataMemberAttribute Require Special Handling for Boolean Properties为什么 DataMemberAttribute 需要对布尔属性进行特殊处理 【发布时间】:2013-09-30 09:37:44 【问题描述】:

我注意到,如果数据协定中的布尔属性不发出默认属性,例如

    [DataMember(Order = 0, IsRequired = true, EmitDefaultValue = false)]
    public bool IsSet  get; set; 

然后将该属性设置为 false 会导致序列化错误。这似乎违反直觉,因为属性已经设置,只是它被设置为 false。解决方案是始终将布尔属性配置为发出默认值,然后 true 将通过线路作为 true,而 false 将作为 false。

只是好奇:这是 System.Runtime.Serialization 中的错误还是布尔类型语义的必然结果?

【问题讨论】:

【参考方案1】:

您的问题有点令人困惑,但我认为您似乎看到的行为不是错误,也不是与布尔值有关。

操作合约被标记为IsRequired 设置为true。默认情况下,EmitDefaultValue 设置为 true,但在发布的代码中,它被设置为 false。

EmitDefaultValue 属性指示是否序列化该值,如果它是默认值(换句话说,如果属性设置为false,它不会根据您当前的定义序列化该属性)。

由于该属性被标记为必需,如果您将值设置为false,则序列化将失败(如果EmitDefaultValue 为假),因为您给出了相互矛盾的指示 - 您是说该属性是序列化所必需的, 但如果是默认值(false)就不要序列化。

在某种程度上我猜你可能会说这是因为布尔值的性质(它要么是真要么是假,而假是默认值),但实际上这是因为IsRequiredEmitDefaultValue 交互的方式。

查看Data Member DefaultValues,特别是“与 IsRequired 的交互”部分。

【讨论】:

我明白你在说什么。 EmitDefaultValue 不关心该值是否已显式分配,只关心该属性的值是否等于该类型的默认值。所以整数的工作原理是一样的:所有值为 0 的整数都将从序列化中删除,除非 EmitDefaultValue 为 true。 正确。请记住,在 .NET 中,变量在声明时确实具有默认值 - 值类型的值(如 int 的 0)和引用类型的 null。使用自动属性时,编译器将为您创建支持字段,因此如果您不明确设置属性,它将具有相应的默认值。【参考方案2】:

为避免冲突,您可以使用可为空的 bool (bool?),因此如果该值显式设置为 false,它将按预期进行序列化。当然,请确保您的系统可以处理可为空的 bool 数据类型。

    [DataMember(Order = 0, IsRequired = true, EmitDefaultValue = false)]
    public bool? IsSet  get; set; 

【讨论】:

以上是关于为啥 DataMemberAttribute 需要对布尔属性进行特殊处理的主要内容,如果未能解决你的问题,请参考以下文章

如何获取具有指定名称的 DataMemberAttribute 的属性?

.Net使用JsonSchema验证Json

complex类 序列化时 IsRequired = true 问题

ef怎么实现只更新指定字段

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥需要softmax函数?为啥不简单归一化?