pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

C#中的==運算符

這篇文章主要介紹了C#中的==運算符,非常不錯,具有參考借鑒價值,需要的朋友可以參考下

在這篇文章中,我們將介紹如下內容:

  • ==運算符與基元類型
  • ==運算符與引用類型
  • ==運算符與String類型
  • ==運算符與值類型
  • ==運算符與泛型

==運算符與基元類型

  我們分別用兩種方式比較兩個整數,第一個使用的是Equals(int)方法,每二個使用的是==運算符:  


 class Program
 {
   static void Main(String[] args)
   {
     int num1 = 5;
    int num2 = 5;
     Console.WriteLine(num1.Equals(num2));
    Console.WriteLine(num1 == num2);
  }
 }

  運行上面的示例,兩個語句出的結果均為true。我們通過ildasm.exe工具進行反編譯,查看IL代碼,了解底層是如何執行的。

  如果您以前從來沒有接觸過IL指令,不過沒關系,在這里您不需要理解所有的指令,我們只是想了解這兩個比較方式的差異。

  您可以看到這樣一行代碼:


  IL_0008: call    instance bool [mscorlib]System.Int32::Equals(int32)

  在這里調用的是int類型Equals(Int32)方法(該方法是IEquatable<Int>接口的實現)。

  現在再來看看使用==運算符比較生成的IL指令:


 IL_0015: ceq

  您可以看到,==運行符使用的是ceq指令,它是使用CPU寄存器來比較兩個值。C#==運算符底層機制是使用ceq指令對基元類型進行比較,而不是調用Equals方法。

==運算符與引用類型

  修改上面的示例代碼,將int類型改為引用類型,編譯后通過ildasm.exe工具反編譯查看IL代碼。


 class Program
 {
   static void Main(String[] args)
   {
     Person p1 = new Person();
     p1.Name = "Person1";
     Person p2 = new Person();
    p2.Name = "Person1";
    Console.WriteLine(p1.Equals(p2));
    Console.WriteLine(p1 == p2);
  }
 }

  上述C#代碼的IL代碼如下所示: 

  我們看到p1.Equals(p2)代碼,它是通過調用Object.Equals(Object)虛方法來比較相等,這是在意料之中的事情;現在我們來看==運算符生成的IL代碼,與基元類型一致,使用的也是ceq指令。

==運算符與String類型

   接來下來看String類型的例子:  


class Program
 {
   static void Main(String[] args)
   {
     string s1 = "Sweet";
     string s2 = String.Copy(s1);
     Console.WriteLine(ReferenceEquals(s1, s2));
     Console.WriteLine(s1 == s2);
    Console.WriteLine(s1.Equals(s2));
  }
 }

  上面的代碼與我們以前看過的非常相似,但是這次我們使用String類型的變量。我們建一個字符串,并付給s1變量,在下一行代碼我們創建這個字符串的副本,并付給另一個變量名稱s2。

  運行上面的代碼,在控制臺輸出的結果如下:

  您可以看到ReferenceEquals返回false,這意味著這兩個變量是不同的實例,但是==運算符和Equals方法返回的均是true。在String類型中,==運算符執行的結果與Equals執行的結果一樣。

  同樣我們使用過ildasm.exe工具反編譯查看生成IL代碼。

  在這里我們沒有看到ceq指令,對String類型使用==運算符判斷相等時,調用的是一個op_equality(string,string)的新方法,該方法需要兩個String類型的參數,那么它到底是什么呢?

  答案是String類型提供了==運算符的重載。在C#中,當我們定義一個類型時,我們可以重載該類型的==運算符;例如,對于以前的例子中我們實現的Person類,如果我們為它重載==運算符,大致的代碼如下:


public class Person
 {
   public string Name { get; set; }
   public static bool operator ==(Person p1, Person p2)
  {
    // 注意這里不能使用==,否則會導致StackOverflowException
    if (ReferenceEquals(p1, p2))
       return true; 
    if (ReferenceEquals(p1, null) || ReferenceEquals(p2, null)) 
      return false; 
     return p1.Name == p2.Name;
   } 
   public static bool operator !=(Person p1, Person p2)
   {
    return !(p1 == p2);
   }
 }

  上面的代碼很簡單,我們實現了==運算符重載,這是一個靜態方法,但這里要注意的是,方法的名稱是perator ==,與靜態方法的相似性;事實上,它們會被由編譯器成一個名稱為op_Equality()的特殊靜態方法。

  為了使用事情更加清楚,我們查看微軟實現的String類型。


  在上面的截圖中,我們可以看到,有兩個運算符的重載,一個用于相等,另一個是不等式運算符,其運算方式完全相同,但是否定等于運算符輸出。需要注意的一點是,如果您想重載一個類型的==運行符的實現,那么您還需要重載!=操作符的實現,否則編譯會報錯。

==運算符與值類型

   在演示值類型的示例前,我們先將Person類型從引用類型改為值類型,Person定義如下:


public struct Person
 {
   public string Name { get; set; }
   public Person(string name)
   {
     Name = name;
   }
   public override string ToString()
   {
     return Name;
   }
 }

  我們將示例代碼改為如下:


 class Program
  {
    static void Main(String[] args)
    {
      Person p1 = new Person("Person1");
      Person p2 = new Person("Person2");
      Console.WriteLine(p1.Equals(p2));
      Console.WriteLine(p1 == p2);
   }
 }

   當我們在嘗試編譯上述代碼時,VS將提示如下錯誤:

  根據錯誤提示,我們需要實現Person結構體的==運算符重載,重載的語句如下(忽略具體的邏輯):


 public static bool operator ==(Person p1, Person p2)
 {
 }
 public static bool operator !=(Person p1, Person p2)
 {
 }

   當添加上面代碼后,重新編譯程序,通過ildasm.exe工具反編譯查看IL代碼,發現值類型==運算符調用也是op_Equality方法。

  關于值類型,我們還需要說明一個問題,在不重寫Equals(object)方法時,該方法實現的原理是通過反射遍歷所有字段并檢查每個字段的相等性,關于這一點,我們不演示;對于值類型,最好重寫該方法。

==運算符與泛型

  我們編寫另一段示例代碼,聲明兩個String類型變量,通過4種不同的方式比較運算:


 public class Program
 {
   public static void Main(string[] args)
   {
     string str = "Sweet";
     string str = string.Copy(str);
     Console.WriteLine(ReferenceEquals(str, str1));
     Console.WriteLine(str.Equals(str1));
     Console.WriteLine(str == str1);
     Console.WriteLine(object.Equals(str, str1));
  }
 }

  輸出的結果如下:

  

  首先,我們使用ReferenceEquals方法判斷兩個String變量都引用相同,接下來我們再使用實例方法Equals(string),在第三行,我們使用==運算符,最后,我們使用靜態方法Object.quals(object,object)(該方法最終調用的是String類型重寫的Object.Equals(object)方法)。我們得到結論是:

ReferenceEquals方法返回false,因為它們不是同一個對象的引用;

String類型的Equals(string)方法返回也是true,因為兩個String類型是相同的(即相同的序列或字符);

==運算符也將返回true,因為這兩個String類型的值相同的;

虛方法Object.Equals也將返回true,這是因為在String類型重寫了方法,判斷的是String是否值相同。

  現在我們來修改一下這個代碼,將String類型改為Object類型:


 public class Program
 {
   public static void Main(string[] args)
   {
     object str = "Sweet";
     object str = string.Copy((string)str);
     Console.WriteLine(ReferenceEquals(str, str1));
     Console.WriteLine(str.Equals(str1));
     Console.WriteLine(str == str1);
    Console.WriteLine(object.Equals(str, str1));
   }
 }

  運行的結果如下:

  第三種方法返回的結果與修改之前不一致,==運算符返回的結果是false,這是為什么呢?

  這是因為==運算符實際上是一個靜態的方法,對一非虛方法,在編譯時就已經決定用調用的是哪一個方法。在上面的例子中,引用類型使用的是ceq指令,而String類型調用是靜態的op_Equality方法;這兩個實例不是同一個對象的引用,所以ceq指令執行后的結果是false。

  再來說一下==運算符與泛型的問題,我們創建一個簡單的方法,通過泛型方法判斷兩個泛型參數是否相等并在控制臺上打印出結果:


 static void Equals<T>(T a, T b)
 {
   Console.WriteLine(a == b);
 }

  但是當我們編譯這段代碼時,VS提示如下錯誤:

  上面顯示的錯誤很簡單,不能使用==運算符比較兩個泛型T。因為T可以是任何類型,它可以是引用類型、值類型,不能提供==運算符的具體實現。

  如果像下面這樣修改一下代碼:


 static void Equals<T>(T a, T b) where T : class
 {
   Console.WriteLine(a == b);
 }

  當我們將泛型類型T改為引用類型,能成功編譯;修改Main方法中的代碼,創建兩個相同的String類型,和以前的例子一樣:  


public class Program
 {
   static void Main(string[] args)
   {
     string str = "Sweet";
     string str1 = string.Copy(str);
     Equals(str, str);
   }
   static void Equals<T>(T a, T b) where T : class
   {
     Console.WriteLine(a == b);
   }
 }

  輸出的結果如下:  

  結果與您預期的結果不一樣吧,我們期待的結果是true,輸出的結果是false。不過仔細思考一下,也許會找到答案,因為泛型的約束是引用類型,==運算符對于引用類型使用的是引用相等,IL代碼可以證明這一點:

  如果我們泛型方法中的==運算符改為使用Equals方法,代碼如下:  


 static void Equals<T>(T a, T b)
 {
   Console.WriteLine(object.Equals(a, b));
 }

  我們改用Equals,也可以去掉class約束;如果我們再次運行代碼,控制臺打印的結果與我們預期的一致,這是因為調用是虛方法object.Equals(object)重寫之后的實現。

  但是其它的問題來了,如果對于值類型,這里就會產生裝箱,有沒有解決的辦法呢?關于這一點,我們直接給出答案,有時間專門來討論這個問題。

  將比較的值類型實現IEquatable<T>接口,并將比較的代碼改為如下,這樣可以避免裝箱:


 static void Equals<T>(T a, T b)
 {
   Console.WriteLine(EqualityComparer<T>.Default.Equals(a, b));
 }

總結

  對于基元類型==運算符的底層機制使用的是ceq指令,通過CPU寄存器進行比較;

  對于引用類型==運算符,它也使用的ceq指令來比較內存地址;

  對于重載==運算符的類型,實際上調用的是op_equality這個特殊的方法;

  盡量保證==操作符重載和Object.Equals(Object)虛方法的寫返回的是相同的結果;

  對于值類型,Equals方法默認是通過反射遍歷所有字段并檢查每個字段的相等性,為了提高性能,我們需要重寫該方法;

  值類型默認情況下不能使用==運算符,需要實現==運算符的重載;

以上所述是小編給大家介紹的C#中的==運算符,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對html5模板網網站的支持!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

主站蜘蛛池模板: 公交驾校-北京公交驾校欢迎您!| 818手游网_提供当下热门APP手游_最新手机游戏下载 | 锌合金压铸-铝合金压铸厂-压铸模具-冷挤压-誉格精密压铸 | 选矿设备-新型重选设备-金属矿尾矿重选-青州冠诚重工机械有限公司 | 合肥防火门窗/隔断_合肥防火卷帘门厂家_安徽耐火窗_良万消防设备有限公司 | 网带通过式抛丸机,,网带式打砂机,吊钩式,抛丸机,中山抛丸机生产厂家,江门抛丸机,佛山吊钩式,东莞抛丸机,中山市泰达自动化设备有限公司 | 合肥防火门窗/隔断_合肥防火卷帘门厂家_安徽耐火窗_良万消防设备有限公司 | 广州物流公司_广州货运公司_广州回程车运输 - 万信物流 | B2B网站_B2B免费发布信息网站_B2B企业贸易平台 - 企资网 | 合肥宠物店装修_合肥宠物美容院装修_合肥宠物医院设计装修公司-安徽盛世和居装饰 | 澳洁干洗店加盟-洗衣店干洗连锁「澳洁干洗免费一对一贴心服务」 干洗加盟网-洗衣店品牌排行-干洗设备价格-干洗连锁加盟指南 | 手板_手板模型制作_cnc手板加工厂-东莞天泓 | 托利多电子平台秤-高精度接线盒-托利多高精度电子秤|百科 | 全自动贴标机-套标机-工业热风机-不干胶贴标机-上海厚冉机械 | 洛阳装修公司-洛阳整装一站式品牌-福尚云宅装饰 | PE一体化污水处理设备_地埋式生活污水净化槽定制厂家-岩康塑业 | Pos机办理_个人商户免费POS机申请-拉卡拉办理网 | 冰晶石|碱性嫩黄闪蒸干燥机-有机垃圾烘干设备-草酸钙盘式干燥机-常州市宝康干燥 | 济南宣传册设计-画册设计_济南莫都品牌设计公司 | 登车桥动力单元-非标液压泵站-非标液压系统-深圳市三好科技有限公司 | 广州工业氧气-工业氩气-工业氮气-二氧化碳-广州市番禺区得力气体经营部 | 开云(中国)Kaiyun·官方网站 - 登录入口 | 玖容气动液压设备有限公司-气液增压缸_压力机_增压机_铆接机_增压器 | 工业CT-无锡璟能智能仪器有限公司| 蒸汽吸附分析仪-进口水分活度仪|康宝百科 | 常州企业采购平台_常州MRO采购公司_常州米孚机电设备有限公司 | 一体化预制泵站-一体化提升泵站-一体化泵站厂家-山东康威环保 | 非标压力容器_碳钢储罐_不锈钢_搪玻璃反应釜厂家-山东首丰智能环保装备有限公司 | 酒瓶_酒杯_玻璃瓶生产厂家_徐州明政玻璃制品有限公司 | 东莞画册设计_logo/vi设计_品牌包装设计 - 华略品牌设计公司 | PC构件-PC预制构件-构件设计-建筑预制构件-PC构件厂-锦萧新材料科技(浙江)股份有限公司 | 嘉兴恒升声级计-湖南衡仪声级计-杭州爱华多功能声级计-上海邦沃仪器设备有限公司 | 胶水,胶粘剂,AB胶,环氧胶,UV胶水,高温胶,快干胶,密封胶,结构胶,电子胶,厌氧胶,高温胶水,电子胶水-东莞聚力-聚厉胶粘 | 西装定制/做厂家/公司_西装订做/制价格/费用-北京圣达信西装 | 天津云仓-天津仓储物流-天津云仓一件代发-顺东云仓 | 成都亚克力制品,PVC板,双色板雕刻加工,亚克力门牌,亚克力标牌,水晶字雕刻制作-零贰捌广告 | 东莞精密模具加工,精密连接器模具零件,自動機零件,冶工具加工-益久精密 | 沈阳网站建设_沈阳网站制作_沈阳网页设计-做网站就找示剑新零售 沈阳缠绕膜价格_沈阳拉伸膜厂家_沈阳缠绕膜厂家直销 | SMC-SMC电磁阀-日本SMC气缸-SMC气动元件展示网 | 浙江华锤电器有限公司_地磅称重设备_防作弊地磅_浙江地磅售后维修_无人值守扫码过磅系统_浙江源头地磅厂家_浙江工厂直营地磅 | 粉末包装机-给袋式包装机-全自动包装机-颗粒-液体-食品-酱腌菜包装机生产线【润立机械】 |