'Object.ReferenceEquals'始终为false,因为它使用值类型进行调用 [英] 'Object.ReferenceEquals' is always false because it is called with a value type
问题描述
当我使用 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?
推荐答案
对于字符串是否要使用Equals
或ReferenceEquals
似乎值得商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 staticObject.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. UsingReferenceEquals
ensures that the setter is applied in case #2 above, whereas usingEquals
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屋!