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

 

posted @ 2020-08-13 15:05  虚青海  阅读(521)  评论(0编辑  收藏  举报