成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

C#中的==運(yùn)算符有什么用-創(chuàng)新互聯(lián)

這篇文章主要為大家展示了“C#中的==運(yùn)算符有什么用”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“C#中的==運(yùn)算符有什么用”這篇文章吧。

專注于為中小企業(yè)提供成都做網(wǎng)站、網(wǎng)站制作服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)和碩免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了成百上千家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

==運(yùn)算符與基元類型

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

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

運(yùn)行上面的示例,兩個(gè)語句出的結(jié)果均為true。我們通過ildasm.exe工具進(jìn)行反編譯,查看IL代碼,了解底層是如何執(zhí)行的。

C#中的==運(yùn)算符有什么用

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

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

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

在這里調(diào)用的是int類型Equals(Int32)方法(該方法是IEquatable<Int>接口的實(shí)現(xiàn))。

現(xiàn)在再來看看使用==運(yùn)算符比較生成的IL指令:

 IL_0015: ceq

您可以看到,==運(yùn)行符使用的是ceq指令,它是使用CPU寄存器來比較兩個(gè)值。C#==運(yùn)算符底層機(jī)制是使用ceq指令對(duì)基元類型進(jìn)行比較,而不是調(diào)用Equals方法。

==運(yùn)算符與引用類型

修改上面的示例代碼,將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代碼如下所示: 

C#中的==運(yùn)算符有什么用

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

==運(yùn)算符與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類型的變量。我們建一個(gè)字符串,并付給s1變量,在下一行代碼我們創(chuàng)建這個(gè)字符串的副本,并付給另一個(gè)變量名稱s2。

運(yùn)行上面的代碼,在控制臺(tái)輸出的結(jié)果如下:

C#中的==運(yùn)算符有什么用

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

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

C#中的==運(yùn)算符有什么用

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

答案是String類型提供了==運(yùn)算符的重載。在C#中,當(dāng)我們定義一個(gè)類型時(shí),我們可以重載該類型的==運(yùn)算符;例如,對(duì)于以前的例子中我們實(shí)現(xiàn)的Person類,如果我們?yōu)樗剌d==運(yùn)算符,大致的代碼如下:

public class Person
 {
   public string Name { get; set; }
   public static bool operator ==(Person p1, Person p2)
  {
    // 注意這里不能使用==,否則會(huì)導(dǎo)致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);
   }
 }

上面的代碼很簡(jiǎn)單,我們實(shí)現(xiàn)了==運(yùn)算符重載,這是一個(gè)靜態(tài)方法,但這里要注意的是,方法的名稱是perator ==,與靜態(tài)方法的相似性;事實(shí)上,它們會(huì)被由編譯器成一個(gè)名稱為op_Equality()的特殊靜態(tài)方法。

為了使用事情更加清楚,我們查看微軟實(shí)現(xiàn)的String類型。

C#中的==運(yùn)算符有什么用

在上面的截圖中,我們可以看到,有兩個(gè)運(yùn)算符的重載,一個(gè)用于相等,另一個(gè)是不等式運(yùn)算符,其運(yùn)算方式完全相同,但是否定等于運(yùn)算符輸出。需要注意的一點(diǎn)是,如果您想重載一個(gè)類型的==運(yùn)行符的實(shí)現(xiàn),那么您還需要重載!=操作符的實(shí)現(xiàn),否則編譯會(huì)報(bào)錯(cuò)。

==運(yùn)算符與值類型

在演示值類型的示例前,我們先將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);
   }
 }

當(dāng)我們?cè)趪L試編譯上述代碼時(shí),VS將提示如下錯(cuò)誤:

C#中的==運(yùn)算符有什么用

根據(jù)錯(cuò)誤提示,我們需要實(shí)現(xiàn)Person結(jié)構(gòu)體的==運(yùn)算符重載,重載的語句如下(忽略具體的邏輯):

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

當(dāng)添加上面代碼后,重新編譯程序,通過ildasm.exe工具反編譯查看IL代碼,發(fā)現(xiàn)值類型==運(yùn)算符調(diào)用也是op_Equality方法。

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

==運(yùn)算符與泛型

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

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

輸出的結(jié)果如下:

C#中的==運(yùn)算符有什么用

首先,我們使用ReferenceEquals方法判斷兩個(gè)String變量都引用相同,接下來我們?cè)偈褂脤?shí)例方法Equals(string),在第三行,我們使用==運(yùn)算符,最后,我們使用靜態(tài)方法Object.quals(object,object)(該方法最終調(diào)用的是String類型重寫的Object.Equals(object)方法)。我們得到結(jié)論是:

ReferenceEquals方法返回false,因?yàn)樗鼈儾皇峭粋€(gè)對(duì)象的引用;

String類型的Equals(string)方法返回也是true,因?yàn)閮蓚€(gè)String類型是相同的(即相同的序列或字符);

==運(yùn)算符也將返回true,因?yàn)檫@兩個(gè)String類型的值相同的;

虛方法Object.Equals也將返回true,這是因?yàn)樵赟tring類型重寫了方法,判斷的是String是否值相同。

現(xiàn)在我們來修改一下這個(gè)代碼,將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));
   }
 }

運(yùn)行的結(jié)果如下:

C#中的==運(yùn)算符有什么用

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

這是因?yàn)?=運(yùn)算符實(shí)際上是一個(gè)靜態(tài)的方法,對(duì)一非虛方法,在編譯時(shí)就已經(jīng)決定用調(diào)用的是哪一個(gè)方法。在上面的例子中,引用類型使用的是ceq指令,而String類型調(diào)用是靜態(tài)的op_Equality方法;這兩個(gè)實(shí)例不是同一個(gè)對(duì)象的引用,所以ceq指令執(zhí)行后的結(jié)果是false。

再來說一下==運(yùn)算符與泛型的問題,我們創(chuàng)建一個(gè)簡(jiǎn)單的方法,通過泛型方法判斷兩個(gè)泛型參數(shù)是否相等并在控制臺(tái)上打印出結(jié)果:

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

但是當(dāng)我們編譯這段代碼時(shí),VS提示如下錯(cuò)誤:

C#中的==運(yùn)算符有什么用

上面顯示的錯(cuò)誤很簡(jiǎn)單,不能使用==運(yùn)算符比較兩個(gè)泛型T。因?yàn)門可以是任何類型,它可以是引用類型、值類型,不能提供==運(yùn)算符的具體實(shí)現(xiàn)。

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

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

當(dāng)我們將泛型類型T改為引用類型,能成功編譯;修改Main方法中的代碼,創(chuàng)建兩個(gè)相同的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);
   }
 }

輸出的結(jié)果如下:  

C#中的==運(yùn)算符有什么用

結(jié)果與您預(yù)期的結(jié)果不一樣吧,我們期待的結(jié)果是true,輸出的結(jié)果是false。不過仔細(xì)思考一下,也許會(huì)找到答案,因?yàn)榉盒偷募s束是引用類型,==運(yùn)算符對(duì)于引用類型使用的是引用相等,IL代碼可以證明這一點(diǎn):

C#中的==運(yùn)算符有什么用

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

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

我們改用Equals,也可以去掉class約束;如果我們?cè)俅芜\(yùn)行代碼,控制臺(tái)打印的結(jié)果與我們預(yù)期的一致,這是因?yàn)檎{(diào)用是虛方法object.Equals(object)重寫之后的實(shí)現(xiàn)。

但是其它的問題來了,如果對(duì)于值類型,這里就會(huì)產(chǎn)生裝箱,有沒有解決的辦法呢?關(guān)于這一點(diǎn),我們直接給出答案,有時(shí)間專門來討論這個(gè)問題。

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

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

總結(jié)

對(duì)于基元類型==運(yùn)算符的底層機(jī)制使用的是ceq指令,通過CPU寄存器進(jìn)行比較;

對(duì)于引用類型==運(yùn)算符,它也使用的ceq指令來比較內(nèi)存地址;

對(duì)于重載==運(yùn)算符的類型,實(shí)際上調(diào)用的是op_equality這個(gè)特殊的方法;

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

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

值類型默認(rèn)情況下不能使用==運(yùn)算符,需要實(shí)現(xiàn)==運(yùn)算符的重載;

以上是“C#中的==運(yùn)算符有什么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司行業(yè)資訊頻道!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站jinyejixie.com,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

新聞標(biāo)題:C#中的==運(yùn)算符有什么用-創(chuàng)新互聯(lián)
分享路徑:http://jinyejixie.com/article32/dijgsc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、做網(wǎng)站ChatGPT、網(wǎng)站收錄、網(wǎng)站導(dǎo)航、域名注冊(cè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計(jì)公司
松江区| 临颍县| 宜川县| 射洪县| 长葛市| 仪征市| 仪征市| 蓬莱市| 上犹县| 白城市| 修水县| 铜陵市| 江达县| 宜州市| 东光县| 峨眉山市| 安图县| 昌吉市| 海阳市| 旅游| 广元市| 绥化市| 中卫市| 武鸣县| 邳州市| 鄄城县| 临沧市| 绥滨县| 宿松县| 金华市| 正阳县| 垦利县| 文山县| 金昌市| 礼泉县| 托克逊县| 晋城| 六安市| 汤原县| 旬邑县| 旬阳县|