首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 比較運算完整指南:六大運算子、各類型語意、IEEE 754 與字串比較陷阱

     編輯:關於C#

C# 定義六大比較運算子 (==, !=, <, >, <=, >=),但其在不同類型 (數值、布林、列舉、字串、委派、參考) 上的語意差異極大。深入理解這些細節,能避免微妙的 Bug 與效能陷阱。

六大運算子總覽

運算子名稱回傳型別
==等於bool
!=不等於bool
<小於bool
>大於bool
<=小於或等於bool
>=大於或等於bool

數值類型:IEEE 754 浮點數語意 (關鍵)

NaN (非數值) 特殊規則

double nan = double.NaN;

nan == nan    // false (NaN 不等於自己!)
nan != nan    // true  (唯一「自己不等於自己」的值)
nan < 0       // false
nan > 0       // false
nan <= 0      // false
nan >= 0      // false

// 關鍵推論:!(x == y) != (x != y) 當 NaN 參與時
// 正確檢查 NaN:double.IsNaN(x)

零值與無窮大

+0.0 == -0.0  // true (正負零相等)
+0.0 > -0.0   // false

double.PositiveInfinity > 1e308  // true
double.NegativeInfinity < -1e308 // true

// 無窮大運算
1.0 / 0.0  // +Infinity
-1.0 / 0.0 // -Infinity
0.0 / 0.0  // NaN

比較順序 (完整順序)

-∞ < -MaxValue < ... < -MinValue < -0.0 == +0.0 < +MinValue < ... < +MaxValue < +∞ < NaN (無序)

整數與浮點數混合比較

// 隱含轉換:int → long → float → double
5 == 5.0        // true (int 轉 double)
5 == 5.0f       // true (int 轉 float)
long.MaxValue == double.MaxValue // false (精度遺失)

// 危險:大整數轉 float 失去精度
long big = 9_000_000_000_000_000_000L;
float f = big; // 精度遺失
big == f       // false! (f 被四捨五入)

布林類型:僅支援等值比較

運算子支援語意
==, !=✅值相等比較
<, >, <=, >=❌編譯錯誤
false == false // true
true != false  // true
// true < false // CS0019: 無法套用運算子

// 關鍵:!= 等價於 ^ (XOR)
bool a = true, b = false;
a != b  // true
a ^ b   // true (相同結果)

列舉類型:隱含支援所有六大運算子

enum Priority { Low = 1, Medium = 2, High = 3 }

Priority p1 = Priority.Medium;
Priority p2 = Priority.High;

p1 < p2        // true (比較底層值 2 < 3)
p1 == p2       // false
p1 >= Priority.Low // true

// 底層機制:((U)p1) op ((U)p2) — 比較基底整數值

字串比較:值語意 vs 參考語意 (重點陷阱)

預定義 == / !=:序數值比較

// 比較字元序列,非參考
"hello" == "hello"        // true
string s1 = "he" + "llo";
string s2 = "hello";
s1 == s2                  // true (不同物件,同值)

// 區分大小寫
"Hello" == "hello"        // false

// null 處理
null == null              // true
"text" == null            // false

參考比較:需明確使用

object.ReferenceEquals(s1, s2) // false (不同實例)
object.ReferenceEquals(s1, "hello") // 可能 true (字串駐留)

文化特定比較:使用 StringComparison

// 忽略大小寫
string.Equals("HELLO", "hello", StringComparison.OrdinalIgnoreCase) // true

// 當前文化特定
"İ".Equals("i", StringComparison.CurrentCulture) // true (土耳其語 İ)

// 序數 (最快、預設 == 行為)
"HELLO".Equals("hello", StringComparison.Ordinal) // false

參考類型:預設參考比較

class Person { public string Name; }

var p1 = new Person { Name = "Alice" };
var p2 = new Person { Name = "Alice" };
var p3 = p1;

p1 == p2  // false (不同參考,除非多載 ==)
p1 == p3  // true (同參考)

// 多載 == 時建議同時多載 !=、Equals、GetHashCode

委派比較:調用清單比較

Action a1 = () => Console.WriteLine(1);
Action a2 = () => Console.WriteLine(1);
Action a3 = a1;

a1 == a2  // false (不同實例,即使方法相同)
a1 == a3  // true (同參考)

Action multi = a1 + a2;
multi == (a1 + a2) // true (同調用清單順序)

自訂類型多載比較運算子:標準模式

public readonly struct Temperature : IEquatable, IComparable
{
    public double Celsius { get; }
    
    public static bool operator ==(Temperature left, Temperature right) 
        => left.Celsius == right.Celsius;
    public static bool operator !=(Temperature left, Temperature right) 
        => !(left == right);
    public static bool operator <(Temperature left, Temperature right) 
        => left.Celsius < right.Celsius;
    public static bool operator >(Temperature left, Temperature right) 
        => left.Celsius > right.Celsius;
    public static bool operator <=(Temperature left, Temperature right) 
        => left.Celsius <= right.Celsius;
    public static bool operator >=(Temperature left, Temperature right) 
        => left.Celsius >= right.Celsius;
    
    // 必須覆寫
    public override bool Equals(object obj) => obj is Temperature t && this == t;
    public bool Equals(Temperature other) => this == other;
    public override int GetHashCode() => Celsius.GetHashCode();
}

最佳實踐總結

  1. 浮點數比較避免 ==/!= — 使用誤差範圍:Math.Abs(a - b) < epsilon
  2. 字串比較明確指定 StringComparison — 避免文化特定行為差異
  3. 自訂類型實作 IEquatable<T> + IComparable<T> — 標準化、效能最佳
  4. 多載 == 必須成對多載 != — 並覆寫 Equals/GetHashCode
  5. 參考類型預設參考比較 — 值比較需多載或用 Equals
  6. 檢查 NaN 用 double.IsNaN() — 非比較運算子

精通各類型比較語意細節,是編寫正確、高效且可移植 C# 程式碼的關鍵基礎能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved