2

当我使用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");
        }
    }
}

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

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

我知道字符串是不可变的,但我似乎对每个属性都收到了这个警告。

ReSharper建议如下:

注意:这包括我的自定义样式,将简单的 getter 放在一行上,反转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");
    }
}

所以它真的引出了一个问题,为什么SlSvcUtil.exe使用ReferenceEquals而不是EqualsifReferenceEquals总是会返回 false?

4

2 回答 2

2

您是否想要使用EqualsReferenceEquals用于字符串似乎值得商榷。 Equals将比较字符串的值,而ReferenceEquals将比较引用 - 但是,由于字符串实习,等效的字符串文字将作为相同的引用出现。例如:

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

那么代码生成算法的作者是如何决定的呢?我能想到的几个考虑因素:

  • 性能:Object.Equals需要一个虚拟方法调用,这可能不如静态方法性能好Object.ReferenceEquals(假设我们正在讨论字符串,它作为引用类型不需要装箱)。
  • 通常你会想要使用ReferenceEquals引用类型——作者可能已经决定不值得为字符串的特殊情况维护单独的代码。
  • 另请注意,在此特定情况下,使用ReferenceEquals防御性选择。usingReferenceEquals确保在上面的情况 #2 中应用 setter,而在这种情况下 using不会Equals应用setter。您可能会想出一些极端情况,即后一种行为可能会引入非常难以检测的错误。

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

于 2014-10-30T21:17:19.340 回答
1

@McGarnagle

但是,由于字符串实习,等效的字符串文字将作为相同的引用出现

字符串并不总是被保留。为了被实习,字符串值需要在编译时知道。IE 只有字符串文字,并且有连接。.NET 运行时的不同版本/构建也有不同的实习。微软 C# 编译器团队的 Eric Lippert 曾写过有关此问题的文章,请参阅:“String interning and String.Empty”Sept 2009

至于比较两个字符串的相等。

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

于 2016-01-08T08:14:26.127 回答