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

C# 減法運算完整指南:數值/列舉/字串/委派語意、溢位與運算子多載模式

     編輯:關於C#

減法運算 (-) 在 C# 中展現豐富的多型行為:支援數值減法、列舉差值計算、委派移除,甚至隱含字串操作 (透過多載)。理解各類型語意差異、溢位邊界與一元負號特性,對正確建模領域邏輯至關重要。

支援減法的類型總覽

類型分類支援形式語意結果類型
整數/浮點數/decimal二元 a - b數值減法較大類型
列舉E - E, E - U差值/減去基底值基底型別 / E
委派D - D移除調用清單D
TimeSpan/DateTime二元減法時間差/時間點減去間隔TimeSpan / DateTime
指標 (unsafe)T* - T*, T* - n元素差值/指標減去位移ptrdiff_t / T*

數值減法:溢位與特殊值

整數溢位

int min = int.MinValue; // -2147483648
int max = int.MaxValue; // 2147483647

// unchecked (預設):環繞
var wrap1 = min - 1;    // 2147483647 (MaxValue)
var wrap2 = max - (-1); // -2147483648 (MinValue)

// checked:拋出 OverflowException
checked { min - 1; }    // Exception

// 長整數避免溢位
long safe = (long)min - 1; // -2147483649L

浮點數特殊值 (IEEE 754)

a - b結果說明
∞ - ∞NaN不定式
∞ - 正常∞保持無窮大
正常 - ∞-∞翻轉符號
0 - 0+0.0正零 (IEEE 規則)
-0 - +0-0.0負零
NaN - 任何NaN傳播

decimal 減法

decimal a = 10.5m, b = 3.2m;
decimal c = a - b; // 7.3m (精確)

// 溢位例外
decimal min = decimal.MinValue;
min - 1; // OverflowException (無 Infinity)

一元負號 (-x) 特性

int x = 5;
int neg = -x; // -5

// 陷阱:最小值取負溢位
int min = int.MinValue; // -2147483648
int negMin = -min;      // -2147483648 (環繞,結果仍為 MinValue!)
checked { -min; }       // OverflowException

// 浮點數:精確翻轉符號
double d = -0.0;
double negD = -d; // +0.0

double nan = double.NaN;
-nan; // NaN (符號位翻轉,但仍為 NaN)

列舉類型減法:兩種形式

enum Priority { Low = 1, Medium = 10, High = 100 }

// 1. E - E → 基底型別 (差值)
int diff = Priority.High - Priority.Low; // 99 (int)

// 2. E - U → E (減去基底值)
Priority p = Priority.High - 50; // 值 50 (但無對應列舉成員)
// 實際編譯為:(Priority)((int)Priority.High - 50)

// 底層機制
// E - E : (U)((U)x - (U)y) → 基底型別
// E - U : (E)((U)x - y) → E

實戰:列舉旗標移除 (實際用 & 運算)

[Flags] enum Perm { Read = 1, Write = 2, Exec = 4 }
Perm p = Perm.Read | Perm.Write | Perm Exec; // 7

// 錯誤:減法非旗標移除
// p = p - Perm.Write; // p = 5 (Read|Exec) 但語意錯誤

// 正確:位元 AND 移除
p &= ~Perm.Write; // p = 5 (Read|Exec)

委派減法:移除調用清單

Action a1 = () => Console.WriteLine("A");
Action a2 = () => Console.WriteLine("B");
Action a3 = () => Console.WriteLine("C");

Action multi = a1 + a2 + a3; // 調用清單: [a1, a2, a3]

// 移除單一委派
multi -= a2; // 清單: [a1, a3]

// 移除不存在的委派:無效果,回傳原清單
multi -= () => Console.WriteLine("X"); // 仍為 [a1, a3]

// 移除多播委派片段
Action pair = a1 + a2;
multi = a1 + a2 + a3;
multi -= pair; // 清單: [a3]

// 完全移除 → null
multi -= multi; // null
multi -= a1;    // null (無例外)

關鍵語意

  • 尋找最後出現的匹配調用清單並移除
  • 不匹配則無操作 (不拋出例外)
  • 結果可能為 null (空委派)

字串減法:不支援 (但可模擬)

// C# 字串無內建減法
// "hello" - "ell" // 編譯錯誤

// 模擬:移除子字串
string Remove(string source, string remove) 
    => source.Replace(remove, "");

// 或使用 Regex
string RemovePattern(string source, string pattern) 
    => Regex.Replace(source, pattern, "");

DateTime/TimeSpan 減法

DateTime now = DateTime.Now;
DateTime past = now.AddDays(-7);

TimeSpan diff = now - past; // 7 天
DateTime future = now + diff; // 回到 now

// TimeSpan - TimeSpan
TimeSpan t1 = TimeSpan.FromHours(5);
TimeSpan t2 = TimeSpan.FromHours(2);
TimeSpan t3 = t1 - t2; // 3 小時

使用者定義型別多載模式

public readonly struct Money : IEquatable
{
    public decimal Amount { get; }
    public string Currency { get; }
    
    public Money(decimal amount, string currency) 
    { Amount = amount; Currency = currency; }
    
    public static Money operator -(Money a, Money b)
    {
        if (a.Currency != b.Currency)
            throw new InvalidOperationException("貨幣不匹配");
        return new Money(a.Amount - b.Amount, a.Currency);
    }
    
    public static Money operator -(Money a) // 一元負號
        => new Money(-a.Amount, a.Currency);
    
    // 隱含轉換輔助
    public static implicit operator Money((decimal Amount, string Currency) t)
        => new Money(t.Amount, t.Currency);
}

效能特性

類型指令延遲備註
整數SUB1 週期極快
浮點數SUBSS/SUBSD3-5 週期SIMD 友善
decimal軟體模擬~50-100 週期128 位整數減法
委派方法呼叫~微秒級清單搜尋+配置新陣列

最佳實踐總結

  1. 整數減法溢位風險 — MinValue - 1 環繞,用 checked 或 long
  2. 浮點數 ∞ - ∞ = NaN — 檢查特殊值避免污染計算
  3. 列舉減法語意特殊 — E-E 回傳基底型別差值,E-U 回傳列舉
  4. 委派減法移除最後匹配 — 非存在無錯誤,結果可能為 null
  5. 旗標移除用位元運算 — flags &= ~Flag,非減法
  6. TimeSpan/DateTime 減法型別安全 — 編譯器保證時間維度正確
  7. 自訂型別多載減法 — 成對多載二元/一元,驗證領域不變量

精通減法運算在各類型上的語意邊界,能精確建模領域邏輯並避免溢位、精度遺失與語意錯誤。

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