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

查看:197
本文介绍了'Object.ReferenceEquals'始终为false,因为它使用值类型进行调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用 SlSvcUtil.exe 创建服务客户端文件时,我看到如下代码:

When I use SlSvcUtil.exe to create my service client files, I see code like this:

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

当我使用 ReSharper 检查它时,收到以下警告:

When I inspect it with ReSharper, I receive the following warning:

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

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

我知道 字符串是不可变的 ,但是我似乎每收到一个警告属性.

I understand that strings are immutable, but I seem to receive this warning for every property.

ReSharper 建议以下内容:

注意:这包括我的自定义样式,将简单的吸气剂放在一行上,反转if,删除多余的object限定词和!= true比较

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

private string CategoryField;

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

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

所以这真的是一个问题,为什么 SlSvcUtil.exe 如果ReferenceEquals总是返回false,为什么会使用ReferenceEquals而不是Equals?

So it really begs the question, why does SlSvcUtil.exe use ReferenceEquals instead of Equals if ReferenceEquals is always going to return false?

推荐答案

对于字符串是否要使用EqualsReferenceEquals似乎值得商bat. Equals将比较字符串的值,而ReferenceEquals将比较引用-但是,由于字符串内部化,等效的字符串文字将作为相同的引用出现.例如:

It seems debatable whether you would want to use Equals or ReferenceEquals for strings. 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. 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:

  • 性能:Object.Equals需要一个虚拟方法调用,其性能可能不如静态Object.ReferenceEquals(假设我们正在谈论字符串,作为参考类型的字符串不需要装箱).
  • 通常,您可能想将ReferenceEquals用于引用类型-作者可能已经决定,对于字符串的特殊情况,不值得单独维护代码.
  • 还请注意,在此特定情况下,使用ReferenceEquals防御性的选择.使用ReferenceEquals可确保在上述情况#2中应用该设置器,而使用Equals在该情况下将应用该设置器.您可能会梦到某个极端的情况,在这种情况下,后一种行为可能会引入一个非常难以发现的错误.
  • 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).
  • 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.
  • Note also that using ReferenceEquals is the defensive choice in this specific instance. Using ReferenceEquals ensures that the setter is applied in case #2 above, whereas using Equals would not apply the setter in that case. You could probably dream up some corner case where the latter behavior could introduce a very hard-to-detect bug.

无论如何,Resharper警告显然是错误的. String是引用类型,而不是值类型,并且(如上例所示)ReferenceEquals实际上可以为字符串值返回true.

Anyway, the Resharper warning is clearly wrong. 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.

这篇关于'Object.ReferenceEquals'始终为false,因为它使用值类型进行调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆