简体   繁体   English

'Object.ReferenceEquals'始终为false,因为它使用值类型进行调用

[英]'Object.ReferenceEquals' is always false because it is called with a value type

When I use SlSvcUtil.exe to create my service client files, I see code like this: 当我使用SlSvcUtil.exe创建服务客户端文件时,我看到如下代码:

private string CategoryField;

[System.Runtime.Serialization.DataMemberAttribute()]
public string Category
{
    get
    {
        return this.CategoryField;
    }
    set
    {
        if ((object.ReferenceEquals(this.CategoryField, value) != true))
        {
            this.CategoryField = value;
            this.RaisePropertyChanged("Category");
        }
    }
}

When I inspect it with ReSharper , I receive the following warning: 当我使用ReSharper检查它时,会收到以下警告:

'Object.ReferenceEquals' is always false because it is called with a value type 'Object.ReferenceEquals'始终为false,因为它使用值类型进行调用

I understand that strings are immutable , but I seem to receive this warning for every property. 我知道字符串是不可变的 ,但是我似乎对每个属性都收到此警告。

ReSharper recommends the following: ReSharper建议以下内容:

Note: This includes my custom styling of putting simple getters on one line, inverting the if , removing the redundant object qualifier and the != true comparison 注意:这包括我的自定义样式,将简单的吸气剂放在一行上,反转if ,删除多余的object限定符和!= true比较

private string CategoryField;

[DataMember]
public string Category
{
    get { return this.CategoryField; }
    set
    {
        if (Equals(this.CategoryField, value)) { return; }

        this.CategoryField = value;
        this.RaisePropertyChanged("Category");
    }
}

So it really begs the question, why does SlSvcUtil.exe use ReferenceEquals instead of Equals if ReferenceEquals is always going to return false? 因此,这确实引出了一个问题:如果ReferenceEquals总是返回false,为什么SlSvcUtil.exe使用ReferenceEquals而不是Equals

It seems debatable whether you would want to use Equals or ReferenceEquals for strings. 是否要对字符串使用EqualsReferenceEquals ,似乎值得商Equals Equals will compare the values of the strings, whereas ReferenceEquals will compare references -- however, due to string interning, equivalent string literals will come out as the same reference. Equals将比较字符串的值,而ReferenceEquals将比较引用-但是,由于字符串内部,等效的字符串文字将作为相同的引用出现。 For example: 例如:

    static void Main(string[] args)
    {
        string x = "hi", y = "hi", z = string.Concat('h', 'i');
        Console.WriteLine(ReferenceEquals(x, y));   // true
        Console.WriteLine(ReferenceEquals(x, z));   // false

        Console.WriteLine(Equals(x, y));   // true
        Console.WriteLine(Equals(x, z));   // true

        Console.ReadLine();
    }

So how did the authors of the code generation algorithm decide? 那么,代码生成算法的作者是如何决定的呢? A couple of considerations I can think of: 我可以想到的几点注意事项:

  • Performance: Object.Equals requires a virtual method call, which is likely less performant than the static Object.ReferenceEquals (given that we are talking about strings, which as reference types do not require boxing). 性能: Object.Equals需要一个虚拟方法调用,这可能比静态Object.ReferenceEquals性能要Object.ReferenceEquals (假设我们正在谈论字符串,作为参考类型的字符串不需要装箱)。
  • Normally you would want to use ReferenceEquals for reference types -- the authors may have decided that it was not worth maintaining separate code for the special case of strings. 通常,您可能希望对引用类型使用ReferenceEquals -作者可能已经决定,不应该为字符串的特殊情况维护单独的代码。
  • Note also that using ReferenceEquals is the defensive choice in this specific instance. 还要注意,在此特定实例中,使用ReferenceEquals防御选择。 Using ReferenceEquals ensures that the setter is applied in case #2 above, whereas using Equals would not apply the setter in that case. 使用ReferenceEquals可确保在上述情况#2中应用了setter,而在使用Equals情况下则不会应用setter。 You could probably dream up some corner case where the latter behavior could introduce a very hard-to-detect bug. 您可能梦到了一些极端情况,在这种情况下,后一种行为可能会引入一个很难检测到的错误。

Anyway, the Resharper warning is clearly wrong. 无论如何,Resharper警告显然是错误的。 String is a reference type, not a value type, and (as demonstrated in the above example) ReferenceEquals can in fact return true for string values. String是引用类型,而不是值类型,并且(如上例所示) ReferenceEquals实际上可以为字符串值返回true

@McGarnagle @McGarnagle

however, due to string interning, equivalent string literals will come out as the same reference 但是,由于字符串实习,等效的字符串文字将作为相同的引用出现

strings are not always interned. 字符串并不总是被固定。 In order to be interned, the string value needs be known at compile time. 为了被嵌入,需要在编译时知道字符串值。 IE only string literals and there concatenations are interned. IE仅是字符串文字,并且存在串联。 Also there is varying interning for different versions / builds of the .NET runtime. 对于.NET运行时的不同版本/版本,还存在不同的实习方法。 Eric Lippert, who was on the C# compiler team at Microsoft, wrote about this issue, see: "String interning and String.Empty" Sept 2009 微软C#编译器团队的埃里克·利珀特(Eric Lippert)撰写了有关此问题的文章,请参阅: “字符串中间和String.Empty” 2009年9月

As for comparing two strings for value equality. 至于比较两个字符串的相等。

if (String.CompareOrdinal (strA, strB) != 0) ... is likely the most efficient. if (String.CompareOrdinal (strA, strB) != 0) ...可能是最有效的。

暂无
暂无

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

相关问题 object.ReferenceEquals或==运算符? - object.ReferenceEquals or == operator? Assert.ReferenceEquals()在Visual Studio Test中Object.ReferenceEquals()返回'false'的位置 - Assert.ReferenceEquals() Passes where Object.ReferenceEquals() returns 'false' in Visual Studio Test Object.ReferenceEquals永远不会命中 - Object.ReferenceEquals never hit Object.ReferenceEquals对于匹配的字符串返回true - Object.ReferenceEquals returns true for matching strings IEnumerable、Where 和 Object.ReferenceEquals 的问题 - Issue with IEnumerable, Where, and Object.ReferenceEquals Object.ReferenceEquals为两个不同的对象输出true - Object.ReferenceEquals prints true for two different objects c#中Object.Equals(object,object)和Object.ReferenceEquals(object,object)之间的区别 - difference between Object.Equals(object,object) and Object.ReferenceEquals(object,object) in c# C#operator ==,StringBuilder.Equals,Object.Equals和Object.ReferenceEquals之间的差异 - C# Differences between operator ==, StringBuilder.Equals, Object.Equals and Object.ReferenceEquals 为什么我要在Equals覆盖中执行object.ReferenceEquals(null,this)? - Why would I ever want to do object.ReferenceEquals(null, this) in Equals override? 参考平等性能差异? ((object)obj1 ==(object)obj2)vs。object.ReferenceEquals(obj1,obj2) - Reference equality performance difference? ((object)obj1 == (object)obj2) vs. object.ReferenceEquals( obj1, obj2 )
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM