首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >!=-运算符对struct失败

!=-运算符对struct失败
EN

Stack Overflow用户
提问于 2018-04-26 12:59:18
回答 1查看 78关注 0票数 3

我有一些类具有XmlSerializer的一些序列化属性,例如XmlElementXmlArray。现在,我也想使用那些现有的属性来进行Json序列化。

为此,我创建了一个从NewtonSoft的DefaultContractResolver派生出来的类

代码语言:javascript
复制
public class XmlToJsonContractResolver : DefaultContractResolver
{
    internal void ConfigureProperty(MemberInfo member, JsonProperty property)
    {
        ConfigureNamedMembers(member, property);
    }

    private static void ConfigureNamedMembers(MemberInfo member, JsonProperty property)
    {
        foreach (var attribute in member.GetCustomAttributesData().Where(x => x.AttributeType.Namespace == typeof(XmlElementAttribute).Namespace))
        { 
            // the elementName may either be stored in the named argument "ElementName" or was provided to the 
            // constructor of the appropriate Xml-attribute
            var item = attribute.NamedArguments?.FirstOrDefault(x => x.MemberName == "ElementName");
            if (item.HasValue && item.Value != default(CustomAttributeNamedArgument))
            {
                property.PropertyName = item.Value.MemberName;
                return;
            }

            // ElementName is provided to constructor of xml-attribute
            throw new NotImplementedException();
        }
    }

现在我有一个测试类来测试上面的ConfigureProperty-method:

代码语言:javascript
复制
private class A
{
    [XmlElement("AnIntAlias")]
    public int AnXmlSerializableInt { get; set; }
}

如您所见,XmlElementAttribute没有命名参数。相反,ElementName-proerty是通过其构造函数设置的,这就是为什么上面的代码首先检查是否有任何命名参数。

这是使用A的代码

代码语言:javascript
复制
var target = new XmlToJsonContractResolver();
var jsonProperty = new JsonProperty { PropertyName = memberName };
var member = typeof(A).GetMember(nameof(A.AnXmlSerializableInt)).First();
target.ConfigureProperty(member, jsonProperty);

var result = jsonProperty.PropertyName;

当我调试这段代码时,满足了第一个条件if (item.HasValue && item.Value != default(CustomAttributeNamedArgument)),这就是为什么我在property.PropertyName = item.Value.MemberName;上得到了一个NullReferenceException

当我在attribute.NamedArguments上添加一个手表(这是一个List<CustomAttributeNamedArgument>,也就是一个值类型列表)时,该列表中没有任何元素,因此FirstOrDefault应该返回该结构的默认值。但是,!=-operator返回true

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-26 13:13:39

这是因为CustomAttributeNamedArgument结构重写了它的等式操作符如下:

代码语言:javascript
复制
public static bool operator ==(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right)
{
     return left.Equals((object) right);
}

public override bool Equals(object obj)
{
    return obj == (ValueType)this;
}

因此,即使它是一个结构,也基本上使用了引用相等的语义。为什么会这样,我不清楚,但这就是你检查失败的原因。即使是这样:

代码语言:javascript
复制
default(CustomAttributeNamedArgument) == default(CustomAttributeNamedArgument);

用这样的语义返回false。

要解决这个问题,您可以使用以下内容

代码语言:javascript
复制
var item = attribute.NamedArguments?.Where(x => x.MemberName == "ElementName")
    .Cast<CustomAttributeNamedArgument?>().FirstOrDefault();                
if (item.HasValue) {
    property.PropertyName = item.Value.MemberName;
    return;
}

或者以类似的方式返回null作为默认值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50043638

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档