1. 程式人生 > 實用技巧 >C# 運算子過載

C# 運算子過載

C#運算子過載

可以重定義或過載 C# 中內建的運算子。因此,程式設計師也可以使用使用者自定義型別的運算子。過載運算子是具有特殊名稱的函式,是通過關鍵字operator後跟運算子的符號來定義的。與其他函式一樣,過載運算子有返回型別和引數列表。

例如,請看下面的函式:

public static Box operator+ (Box b, Box c)
{
   Box box = new Box();
   box.length = b.length + c.length;
   box.breadth = b.breadth + c.breadth;
   box.height = b.height + c.height;
   
return box; }

上面的函式為使用者自定義的類 Box 實現了加法運算子(+)。它把兩個 Box 物件的屬性相加,並返回相加後的 Box 物件。

運算子過載的實現

        class User
        {
            private int fans;
            private int follows;
            public void setFans(int fan)
            {
                fans = fan;
            }
            public
void setFollows(int follw) { follows = follw; } public int getDiffer() { return (fans+follows)-Math.Max(fans, follows); } //過載運算子 public static User operator+ (User ua,User ub) { User uc
= new User(); uc.fans = ua.fans + ub.fans; uc.follows = ua.follows + ub.follows; return uc; } } }
Ua differ : 114514
Ub differ : 42
Uc differ : 114556

operator 關鍵字用於在類或結構宣告中宣告運算子。運算子宣告可以採用下列四種形式之一:

public static result-type operator unary-operator ( op-type operand )
public static result-type operator binary-operator ( op-type operand, op-type2 operand2 )
public static implicit operator conv-type-out ( conv-type-in operand )
public static explicit operator conv-type-out ( conv-type-in operand )

引數:

  • result-type 運算子的結果型別。
  • unary-operator 下列運算子之一:+ - ! ~ ++ — true false
  • op-type 第一個(或唯一一個)引數的型別。
  • operand 第一個(或唯一一個)引數的名稱。
  • binary-operator 其中一個:+ - * / % & | ^ << >> == != > < >= <=
  • op-type2 第二個引數的型別。
  • operand2 第二個引數的名稱。
  • conv-type-out 型別轉換運算子的目標型別。
  • conv-type-in 型別轉換運算子的輸入型別。

注意:

前兩種形式聲明瞭使用者定義的過載內建運算子的運算子。並非所有內建運算子都可以被過載(請參見可過載的運算子)。op-type 和 op-type2 中至少有一個必須是封閉型別(即運算子所屬的型別,或理解為自定義的型別)。例如,這將防止重定義整數加法運算子。

後兩種形式聲明瞭轉換運算子。conv-type-in 和 conv-type-out 中正好有一個必須是封閉型別(即,轉換運算子只能從它的封閉型別轉換為其他某個型別,或從其他某個型別轉換為它的封閉型別)。

運算子只能採用值引數,不能採用 ref 或 out 引數。

C# 要求成對過載比較運算子。如果過載了==,則也必須過載!=,否則產生編譯錯誤。同時,比較運算子必須返回bool型別的值,這是與其他算術運算子的根本區別。

C# 不允許過載=運算子,但如果過載例如+運算子,編譯器會自動使用+運算子的過載來執行+=運算子的操作。

運算子過載的其實就是函式過載。首先通過指定的運算表示式呼叫對應的運算子函式,然後再將運算物件轉化為運算子函式的實參,接著根據實參的型別來確定需要呼叫的函式的過載,這個過程是由編譯器完成。

任何運算子宣告的前面都可以有一個可選的屬性(C# 程式設計指南)列表。

可過載和不可過載運算子

下表描述了 C# 中運算子過載的能力:

運算子描述
+, -, !, ~, ++, -- 這些一元運算子只有一個運算元,且可以被過載。
+, -, *, /, % 這些二元運算子帶有兩個運算元,且可以被過載。
==, !=, <, >, <=, >= 這些比較運算子可以被過載。
&&, || 這些條件邏輯運算子不能被直接過載。
+=, -=, *=, /=, %= 這些賦值運算子不能被過載。
=, ., ?:, ->, new, is, sizeof, typeof 這些運算子不能被過載。

例項

 public static void run()
        {
            User ua = new User();
            ua.setFans(114514);
            ua.setFollows(1919810);
            Console.WriteLine($"Ua differ : {ua.getDiffer()}");
            User ub = new User();
            ub.setFans(42);
            ub.setFollows(618);
            Console.WriteLine($"Ub differ : {ub.getDiffer()}");
            User uc = ua + ub;
            Console.WriteLine($"Uc differ : {uc.getDiffer()}");
            Console.WriteLine($"Ua-Ub differ : {(ua- ub).getDiffer()}");
            Console.WriteLine($"Ua+Ub differ : {(ua+ ub).getDiffer()}");
            Console.WriteLine($"Ua*Ub differ : {(ua * ub).getDiffer()}");
            Console.WriteLine($"Ua/Ub differ : {(ua / ub).getDiffer()}");
            Console.WriteLine($"Ua>Ub  : {(ua > ub)}");
            Console.WriteLine($"Ua<Ub  : {(ua < ub)}");
            Console.WriteLine($"Ua<=Ub  : {(ua <= ub)}");
            Console.WriteLine($"Ua>=Ub  : {(ua >= ub)}");
            Console.WriteLine($"Ua!=Ub  : {(ua != ub)}");
            Console.WriteLine($"Ua==Ub  : {(ua == ub)}");
        }
        class User
        {
            private int fans;
            private int follows;
            public void setFans(int fan)
            {
                fans = fan;
            }
            public void setFollows(int follw)
            {
                follows = follw;
            }
            public int getDiffer()
            {
                return (fans+follows)-Math.Max(fans, follows);
            }
            //過載運算子
            public static User operator+ (User ua,User ub)
            {
                User uc = new User();
                uc.fans = ua.fans + ub.fans;
                uc.follows = ua.follows + ub.follows;
                return uc;
            }
            public static User operator /(User ua, User ub)
            {
                User uc = new User();
                uc.fans = ua.fans / ub.fans;
                uc.follows = ua.follows / ub.follows;
                return uc;
            }
            public static User operator *(User ua, User ub)
            {
                User uc = new User();
                uc.fans = ua.fans * ub.fans;
                uc.follows = ua.follows * ub.follows;
                return uc;
            }
            public static User operator -(User ua, User ub)
            {
                User uc = new User();
                uc.fans = ua.fans - ub.fans;
                uc.follows = ua.follows - ub.follows;
                return uc;
            }
            public static bool operator <(User ua, User ub)
            {
                return (ua.fans + ua.follows < ub.fans + ub.follows);
            }
            public static bool operator >(User ua, User ub)
            {
                return (ua.fans + ua.follows > ub.fans + ub.follows);
            }
            public static bool operator <=(User ua, User ub)
            {
                return (ua.fans+ua.follows <= ub.fans+ub.follows) ;
            }
            public static bool operator >=(User ua, User ub)
            {
                return (ua.fans + ua.follows >= ub.fans + ub.follows) ;
            }
            public static bool operator!=(User ua, User ub)
            {
                return (ua.fans != ub.fans) | (ua.follows != ub.follows);;
            }
            public static bool operator==(User ua, User ub)
            {
                return (ua.fans==ub.fans)&&(ua.follows==ub.follows);
            }
        }

Ua differ : 114514
Ub differ : 42
Uc differ : 114556
Ua-Ub differ : 114472
Ua+Ub differ : 114556
Ua*Ub differ : 4809588
Ua/Ub differ : 2726
Ua>Ub  : True
Ua<Ub  : False
Ua<=Ub  : False
Ua>=Ub  : True
Ua!=Ub  : True
Ua==Ub  : False