C#中相等的判断

我主要是用例子来说明一下问题:
首先说明一下string字符串,string它是一个引用类型的,只不过是它拥有了值类型的特征,
而通过书中的介绍
ReferenceEquals方法不能继承,它用来专门比较引用类型是否相等,所以它是比较引用的首选,有了它我们可以毫无顾虑的判断,并且简单,看例子:
using System;
using System.Collections.Generic;
using System.Text;

namespace fanxing
{
    
class Class4
    
{


    }


    
class Application2
    
{

        
static void Main(string[] args)
        
{
            Class4 aclass4 
= new Class4();
            Class4 bclass4 
= new Class4();

            
//bclass4=aclass4; 这里加了注释,去掉注释后比较的结果完全不一样
            if (Object.ReferenceEquals(aclass4, bclass4))
            
{

                Console.Write(aclass4.GetHashCode() 
+ "===" + bclass4.GetHashCode());
            }

            
else
            
{

                Console.Write(
"false");
            }


int a=5;
int b=5;

if (Object.ReferenceEquals(a, b)) //这里比较值类型,所以肯定是false毫无疑问,它不是用来比较值类型的
            {

                Console.Write(a.GetHashCode() 
+ "===" + b.GetHashCode());
            }

            
else
            
{

                Console.Write(
"false");
            }


            
char[] c1 = new char[] 'a''a''a' };
            
char[] c2 = new char[] 'a''a''a' };

            
string str1 = "aaa";
            String a 
= "12345";
            String b 
= "";
            String c 
= "12345";
            b 
= b + '1';
            b 
= b + '2';
            b 
= b + '3';
            b 
= b + '4';
            b 
= b + '5';
            
string str2 = new String(c1);
            
string str3 = str2;
            
string str4 = "aaa";

            
//int aaa = 5;
            
//int bbb = 5;


            
if (Object.ReferenceEquals(a, c))  //比较字符串,已经介绍过字符串是特殊的引用类型
            {

                Console.Write(str3.GetHashCode() 
+ "===" + str2.GetHashCode());
            }

            
else
            
{

                Console.Write(
"false");
            }


            Console.Read();
        }

    }

}

上面的例子再次可以证明既然它能比较出连个字符串是否相等,就证明字符串肯定是引用类型,
再者如果比较字符串str1与str2,答案是不相等,因为str2新建了一个对象(new),所以两者不存在引用关系,
肯定是false,而我们再次再介绍一下,看了源码我发现string类没有重写“+"这个运算符号,所以我们在利用字符串进行相加时,只是单纯意义上的字符连接,可能不会像java一样每加一次会创建新对象,于是当我们进行字符串a和b进行比较时,会发现仍然相等,所以说明两者出于同一个对象,大家还有疑问时我们对字符串进行直接复制,就会new对象呢?答案是不会,看了java对此的解释,通常字符串有一个STRING池.当我们进行字符串直接复制时,都会通过这个string池,如果在string池中找到已有的字符串,那么就指向同一个字符串地址,与我们new一个string类是完全不一样。
继续介绍
equal和==在自定义类型是ValueType的时候要改写

当自定义类型是ReferenceType的时候,如果想改变RefrenceType默认的用对象标志判
等的方式,可以改写equal

当自定义类型是RefrenceType的时候,最好不要改写operator==.
还有需要注意的是==比较对于非自定义的值类型就是比较值得大小,
而对于比较引用类型,就是比较是否出自由同一个对象,
对于自定义的值类型如struct可以自己来重写,
对于自定义的引用类型class最好不要用来重写,
并且重写了==就需要重写!=还要重写equal,如果重写了equal就需要重写GetHashCode方法,
因为两者要相等就必须该方法返回值要相等。
using System;
using System.Collections.Generic;
using System.Text;

namespace fanxing
{
    
class car
    
{
        
private int speed;
        
private int num;
        
public car(int speed,int num)
        
{
            
this.speed = speed;
            
this.num=num;
        }


     

      
        
/*public override bool Equals(object x)
        {
            if (!(x is car))
            {
                return false;
            }
            else
            {
                return this == x as car;
            }
        }
*/


  
public override bool Equals( object right )

  
{


    
if (right == null)

      
return false;

    
if (object.ReferenceEquals( this, right ))

      
return true;


    
if (this.GetType() != right.GetType())

      
return false;


    
return CompareFooMembers(

      
this, right as car  );

  }


        
public bool CompareFooMembers(car aaa,car bbb)
        
{
            
if (aaa.speed == bbb.speed)
            
{
                
return true;
            }

            
else 
            
{
                
return false;
            }

        }


        
public override int GetHashCode()
        
{
            
return speed;
        }



    }




   
    
class Application1
    
{

       
static void Main(string[] args)
         
{
             car acar 
=new car(500,5);
             car bcar 
= new car(500,9);
             
if (acar.Equals(bcar))
             
{
                 Console.Write(acar.GetHashCode() 
+ "----" + bcar.GetHashCode());
             }

             
else
             
{
                 Console.Write(
"false");
             }

  
             Console.Read();
         }

    }


 }

注意我上面的例子定义了两个重写equal,用第一个的话为false因为它调用了==比较,我们介绍过==比较对象时是要比较两个是否出于一个对象,显然不是。加上这句acar=bcar;结果就是相等了。
再看第二种方法,因为我们是自定义的类,所以我们根据我们的需求判断两个对象相等的条件,这里我们选择speed,只要两个对象speed相等我们就判断这两个对象是相等的。
具体实现看代码大家已经八九不离十了,而大家看了我重写的
GetHashCode(),里面返回speed,这点需要说明的是,我提过重写equal必须要重写该方法要返回一样的值,那这个值什么?这里我选择了speed,当然我这个写法太简单了,对于重写GetHashCode()的规则很多,但道理都是一样的那就是:相等的对象必须返回相同的GetHashCode(),这个时候你就可以定里面返回的东西啦。
对于equal在比较非自定义的值类型时与==相同,
对比较引用类型的时候也是判断是否出于同一个对象,
下面我们接着介绍string,
既然string是引用类型,那
using System;
using System.Collections.Generic;
using System.Text;

namespace fanxing
{
    
class Class4
    
{


    }


    
class Application2
    
{

        
static void Main(string[] args)
        
{

            
char[] c1 = new char[] 'a''a''a' };
            
char[] c2 = new char[] 'a''a''a' };

            
string str1 = "aaa";
            String a 
= "12345";
            String b 
= "";
            String c 
= "12345";
            b 
= b + '1';
            b 
= b + '2';
            b 
= b + '3';
            b 
= b + '4';
            b 
= b + '5';  
            
string str2 = new String(c1);
            
string str3 = str2;
            
string str4 = "aaa";

            
int aaa = 5;
            
int bbb = 5;


            
if (Object.ReferenceEquals(a,b))
            
{

                Console.Write(str3.GetHashCode()
+"==="+str2.GetHashCode());
            }

            
else
            
{
                
                Console.Write(
"false");
            }



            
if (str1 == str2)
            
{
                Console.Write(
"true");
            }

            
else
            
{
                Console.Write(
"false");
            }


            
if (aaa.Equals(bbb))
            
{
                Console.Write(
"true");
            }

            
else
            
{
                Console.Write(
"false");
            }

            
            Console.Read();
        }

    }

}


命名str1和str2不是同一个引用(前面已经介绍),但为什么后面的比较确相等呢?
我们看源代码可知道string它重写了==和equal这两个方法,我们不追究里面的实现,
但至少它里面的实现应该是和我们前面提到的speed比较相似,并没有比较对象的引用,
而是比较对象的值


posted @ 2008-04-15 18:41  酷咖啡  阅读(1002)  评论(0编辑  收藏  举报