标题:c#菜鸟问题
只看楼主
没有注册
Rank: 1
等 级:新手上路
帖 子:34
专家分:0
注 册:2007-8-16
得分:0 

又是弱智问题

==和equal得看具体实现的方法是比较什么 一般自定义的类型 得自己复写该方法


ReferenceEqual是比较是否同一个引用

2007-08-16 11:11
立志成佛
Rank: 1
等 级:新手上路
威 望:2
帖 子:314
专家分:0
注 册:2006-11-1
得分:0 

谢谢


曾经的曾经已不在
2007-08-16 11:38
没有注册
Rank: 1
等 级:新手上路
帖 子:34
专家分:0
注 册:2007-8-16
得分:0 
以下是引用立志成佛在2007-8-16 11:38:08的发言:

谢谢


哈哈 你气到了吧

开玩笑的

我是chenjin145 很久没来了 过来冒冒

2007-08-16 11:45
立志成佛
Rank: 1
等 级:新手上路
威 望:2
帖 子:314
专家分:0
注 册:2006-11-1
得分:0 
以下是引用没有注册在2007-8-16 11:45:05的发言:


哈哈 你气到了吧

开玩笑的

我是chenjin145 很久没来了 过来冒冒

好久不见 好想你啊


曾经的曾经已不在
2007-08-16 12:19
立志成佛
Rank: 1
等 级:新手上路
威 望:2
帖 子:314
专家分:0
注 册:2006-11-1
得分:0 
另:你太低估我虚心求教的本质了

曾经的曾经已不在
2007-08-16 12:20
卡卡艾
Rank: 6Rank: 6
等 级:贵宾
威 望:22
帖 子:672
专家分:0
注 册:2007-4-3
得分:0 
顺便问下:什么情况下能用到引用相等呢?

革命尚未成功,同志仍需努力-----+++
2007-08-16 12:24
立志成佛
Rank: 1
等 级:新手上路
威 望:2
帖 子:314
专家分:0
注 册:2006-11-1
得分:0 
Equals是从Object继承而来的,默认的Object.Equals实现是对引用进行比较,因此如果继承类不对该方法进行重写,则就是默认的对引用进行比较。==是运算符,你必须手动对你自己的类型实现“==”,如果你的实现是对引用(Equals为默认实现时)进行比较,则这两个就是一样的,如果不是,那么在Equals为默认实现时,这两个就是不同的。

曾经的曾经已不在
2007-08-16 12:26
立志成佛
Rank: 1
等 级:新手上路
威 望:2
帖 子:314
专家分:0
注 册:2006-11-1
得分:0 
没事不要重载引用类的相等操作符……
刚刚重载顺手了,把自己定义的一个类的==重载了。结果比较惨,后知后觉发现一个绕不过去的地方:
如果用Equals调用重载的==,那么如果表达式是 obj == null,那么,挂了……
如果==调用Equals,更不用说,要是类型不对,都难判断的……况且,null也没有GetType()一说……

最后查到到msdn上这样说

Implementing the Equality Operator (==) on Reference Types

Most languages do provide a default implementation of the equality operator (==) for reference types. Therefore, you should use care when implementing == on reference types. Most reference types, even those that implement the Equals method, should not override ==.

所以,算是个教训,没事不要重载 类 的==操作符……

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=601363


曾经的曾经已不在
2007-08-16 12:28
立志成佛
Rank: 1
等 级:新手上路
威 望:2
帖 子:314
专家分:0
注 册:2006-11-1
得分:0 
C# 语言规范

7.9.6 引用类型相等运算符

预定义的引用类型相等运算符为:

bool operator ==(object x, object y);
bool operator !=(object x, object y);

这些运算符返回两个引用是相等还是不相等的比较结果。

由于预定义的引用类型相等运算符接受 object 类型的操作数,因此它们适用于所有那些没有为自己声明适用的 operator ==operator != 成员的类型。相反,任何适用的用户定义的相等运算符都有效地隐藏上述预定义的引用类型相等运算符。

预定义引用类型相等运算符要求操作数是引用类型值或 null 值;此外,它们还要求存在从一种操作数类型到另一种操作数类型的标准隐式转换(第 6.3.1 节)。除非这两个条件都为真,否则将发生编译时错误。这些规则中值得注意的含义是:

  • 使用预定义的引用类型相等运算符比较两个在编译时已能确定是不相同的引用时,会导致编译时错误。例如,如果操作数的编译时类型分属两个类类型 AB,并且 AB 都不从对方派生,则两个操作数不可能引用同一对象。因此,此运算被认为是编译时错误。
  • 预定义的引用类型相等运算符不允许比较值类型操作数。因此,除非结构类型声明自己的相等运算符,否则不可能比较该结构类型的值。
  • 预定义的引用类型相等运算符从不会导致对它们的操作数执行装箱操作。执行此类装箱操作毫无意义,这是因为对新分配的已装箱实例的引用必将不同于所有其他引用。

对于 x == yx != y 形式的运算,如果存在任何适用的 operator ==operator !=,运算符重载决策(第 7.2.4 节)规则将选择该运算符而不是上述的预定义的引用类型相等运算符。不过,始终可以通过将一个或两个操作数显式强制转换为 object 类型来选择预定义的引用类型相等运算符。示例

using System;
class Test
{
   static void Main() {
      string s = "Test";
      string t = string.Copy(s);
      Console.WriteLine(s == t);
      Console.WriteLine((object)s == t);
      Console.WriteLine(s == (object)t);
      Console.WriteLine((object)s == (object)t);
   }
}

产生输出

True
False
False
False

变量 st 引用两个包含相同字符的不同 string 实例。第一个比较输出 True,这是因为是在两个操作数都为 string 类型时选定预定义的字符串相等运算符(第 7.9.7 节)。其余的比较全都输出 False,这是因为是在一个或两个操作数为 object 类型时选定预定义的引用类型相等运算符。

注意,以上技术对值类型没有意义。示例

class Test
{
   static void Main() {
      int i = 123;
      int j = 123;
      System.Console.WriteLine((object)i == (object)j);
   }
}

输出 False,这是因为强制转换创建对已装箱 int 值的两个单独实例的引用。


曾经的曾经已不在
2007-08-16 12:31
立志成佛
Rank: 1
等 级:新手上路
威 望:2
帖 子:314
专家分:0
注 册:2006-11-1
得分:0 
回复:(立志成佛)C# 语言规范 7.9....

以前一直没有关心这个问题,被别人问起,特记录一下. ( From csdn)

在讨论了运算符,并简要介绍了等于运算符后,就应考虑在处理类和结构的实例时相等意味着什么。理解对象相等比较的机制对编写逻辑表达式非常重要,另外,对实现运算符重载和数据类型转换也非常重要,本章的后面将讨论运算符重载。

对象相等比较的机制对于引用类型(类的实例)的比较和值类型(基本数据类型,结构或枚举的实例)的比较来说是不同的。下面分别介绍引用类型和值类型的相等比较。

5.3.1 引用类型的相等比较

System.Object的一个初看上去令人惊讶的方面是它定义了3个不同的方法,来比较对象的相等性:ReferenceEquals()和Equals()的两个版本。再加上比较运算符==,实际上有4种进行相等比较的方式。这些方法有一些微妙的区别,下面就介绍这些方法。

1. ReferenceEquals()方法

ReferenceEquals()是一个静态方法,测试两个引用是否指向类的同一个实例,即两个引用是否包含内存中的相同地址。作为静态方法,它不能重写,所以只能使用System.Object的实现代码。如果提供的两个引用指向同一个对象实例,ReferenceEquals()总是返回true,否则就返回false。但是它认为null等于null:

SomeClass x, y;

x = new SomeClass();

y = new SomeClass();

bool B1 = ReferenceEquals(null, null); //return true

bool B2 = ReferenceEquals(null, x); //return false

bool B3 = ReferenceEquals(x, y); //return false because x and y

//point to different objects

2. 虚拟的Equals()方法

Equals()虚拟版本的System.Object实现代码也比较引用。但因为这个方法是虚拟的,所以可以在自己的类中重写它,按值来比较对象。特别是如果希望类的实例用作字典中的键,就需要重写这个方法,以比较值。否则,根据重写Object.GetHashCode()的方式,包含对象的字典类要么不工作,要么工作的效率非常低。在重写Equals()方法时要注意,重写的代码不会抛出异常。这是因为如果抛出异常,字典类就会出问题,一些在内部调用这个方法的.NET基类也可能出问题。

3. 静态的Equals()方法

Equals()的静态版本与其虚拟实例版本的作用相同,其区别是静态版本带有两个参数,并对它们进行相等比较。这个方法可以处理两个对象中有一个是null的情况,因此,如果一个对象可能是null,这个方法就可以抛出异常,提供了额外的保护。静态重载版本首先要检查它传送的引用是否为null。如果它们都是null,就返回true(因为null与null相等)。如果只有一个引用是null,就返回false。如果两个引用都指向某个对象,它就调用Equals()的虚拟实例版本。这表示在重写Equals()的实例版本时,其效果相当于也重写了静态版本。

4. 比较运算符==

最好将比较运算符看作是严格值比较和严格引用比较之间的中间选项。在大多数情况下,下面的代码:

bool b = (x == y); //x, y object references

表示比较引用。但是,如果把一些类看作值,其含义就会比较直观。在这些情况下,最好重写比较运算符,以执行值的比较。后面将讨论运算符的重载,但显然它的一个例子是System.String类,Microsoft重写了这个运算符,比较字符串的内容,而不是它们的引用。

5.3.2 值类型的相等比较

在进行值类型的相等比较时,采用与引用类型相同的规则:ReferenceEquals()用于比较引用,Equals()用于比较值,比较运算符可以看作是一个中间项。但最大的区别是值类型需要装箱,才能把它们转换为引用,才能对它们执行方法。另外,Microsoft已经在System.ValueType类中重载了实例方法Equals(),以便对值类型进行合适的相等测试。如果调用sA.Equals(sB),其中sA和sB是某个结构的实例,则根据sA和sB是否在其所有的字段中包含相同的值,而返回true或false。另一方面,在默认情况下,不能对自己的结构重载==运算符。在表达式中使用(sA==sB)会导致一个编译错误,除非在代码中为结构提供了==的重载版本。

另外,ReferenceEquals()在应用于值类型时,总是返回false,因为为了调用这个方法,值类型需要装箱到对象中。即使使用下面的代码:

bool b = ReferenceEquals(v, v); //v is a variable of some value type

也会返回false,因为在转换每个参数时,v都会被单独装箱,这意味着会得到不同的引用。调用ReferenceEquals()来比较值类型实际上没有什么意义。

尽管System.ValueType提供的Equals()默认重载肯定足以应付绝大多数自定义的结构,但仍可以为自己的结构重写它,以提高性能。另外,如果值类型包含作为字段的引用类型,就需要重写Equals(),以便为这些字段提供合适的语义,因为Equals()的默认重写版本仅比较它们的地址。


曾经的曾经已不在
2007-08-16 12:33



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-162836-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.095381 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved