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 对象。

运算符重载的实现

下面通过完整的示例来演示一下运算符重载:
using System;

namespace c.biancheng.net
{
    class Box
    {
        private double length;      // 长度
        private double breadth;     // 宽度
        private double height;      // 高度

        public double getVolume()
        {
            return length * breadth * height;
        }
        public void setLength( double len )
        {
            length = len;
        }

        public void setBreadth( double bre )
        {
            breadth = bre;
        }

        public void setHeight( double hei )
        {
            height = hei;
        }
        // 重载 + 运算符,把两个 Box 对象相加
        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;
        }
    }
    class Demo
    {
        static void Main(string[] args) 
        {
            Box Box1 = new Box();         // 声明 Box1,类型为 Box
            Box Box2 = new Box();         // 声明 Box2,类型为 Box
            Box Box3 = new Box();         // 声明 Box3,类型为 Box
            double volume = 0.0;          // 体积

            // Box1 详述
            Box1.setLength(6.0);
            Box1.setBreadth(7.0);
            Box1.setHeight(5.0);

            // Box2 详述
            Box2.setLength(12.0);
            Box2.setBreadth(13.0);
            Box2.setHeight(10.0);

            // Box1 的体积
            volume = Box1.getVolume();
            Console.WriteLine("Box1 的体积: {0}", volume);

            // Box2 的体积
            volume = Box2.getVolume();
            Console.WriteLine("Box2 的体积: {0}", volume);

            // 把两个对象相加
            Box3 = Box1 + Box2;

            // Box3 的体积
            volume = Box3.getVolume();
            Console.WriteLine("Box3 的体积: {0}", volume);
            Console.ReadKey();
        }
    }
}
运行结果如下:

Box1 的体积: 210
Box2 的体积: 1560
Box3 的体积: 5400

可重载与不可重载的运算符

下表提供了 C# 运算符可重载性的相关信息:

运算符 可重载性
+、-、!、~、++、-- 这些一元运算符可以进行重载
+、-、*、/、%、&、|、^、<<、>>、=、!=、<、>、<=、>= 这些二元运算符可以进行重载,需要注意的是某些运算符必须成对重载
&&、||  无法重载逻辑运算符
(type)var_name 强制类型转换运算符不能重载
+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=     复合赋值运算符不能显式重载。 但在重载二元运算符时,也会隐式重载相应的复合赋值运算符,例如重载了+运算符也会隐式的重载+=
^、=、.、?.、?  :  、??、??=、..、->、=>、as、await、checked、unchecked、default、delegate、is、nameof、new、sizeof、stackalloc、switch、typeof   这些运算符无法进行重载

注意:比较运算符必须成对重载,也就是说,如果重载一对运算符中的任意一个,则另一个运算符也必须重载。比如 == != 运算符、< > 运算符、<= >= 运算符。

【示例】下面通过具体示例来演示一下:
using System;

namespace c.biancheng.net
{
    class Box
    {
        private double length;      // 长度
        private double breadth;     // 宽度
        private double height;      // 高度

        public double getVolume()
        {
            return length * breadth * height;
        }
        public void setLength( double len )
        {
            length = len;
        }

        public void setBreadth( double bre )
        {
            breadth = bre;
        }

        public void setHeight( double hei )
        {
            height = hei;
        }
        // 重载 + 运算符来把两个 Box 对象相加
        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;
        }

        public static bool operator== (Box lhs, Box rhs)
        {
            bool status = false;
            if (lhs.length == rhs.length && lhs.height == rhs.height && lhs.breadth == rhs.breadth)
            {
                status = true;
            }
            return status;
        }
        public static bool operator!= (Box lhs, Box rhs)
        {
            bool status = false;
            if (lhs.length != rhs.length || lhs.height != rhs.height || lhs.breadth != rhs.breadth)
            {
                status = true;
            }
            return status;
        }
        public override bool Equals(object o)
        {
            if(o==null) return false;
            if(GetType() != o.GetType()) return false;
            return true;
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public static bool operator <(Box lhs, Box rhs)
        {
            bool status = false;
            if (lhs.length < rhs.length && lhs.height < rhs.height && lhs.breadth < rhs.breadth)
            {
                status = true;
            }
            return status;
        }

        public static bool operator >(Box lhs, Box rhs)
        {
            bool status = false;
            if (lhs.length > rhs.length && lhs.height > rhs.height && lhs.breadth > rhs.breadth)
            {
                status = true;
            }
            return status;
        }

        public static bool operator <=(Box lhs, Box rhs)
        {
            bool status = false;
            if (lhs.length <= rhs.length && lhs.height <= rhs.height && lhs.breadth <= rhs.breadth)
            {
                status = true;
            }
            return status;
        }

        public static bool operator >=(Box lhs, Box rhs)
        {
            bool status = false;
            if (lhs.length >= rhs.length && lhs.height >= rhs.height && lhs.breadth >= rhs.breadth)
            {
                status = true;
            }
            return status;
        }
        public override string ToString()
        {
            return String.Format("({0}, {1}, {2})", length, breadth, height);
        }
    }
    class Demo
    {
        static void Main(string[] args) 
        {
            Box Box1 = new Box();          // 声明 Box1,类型为 Box
            Box Box2 = new Box();          // 声明 Box2,类型为 Box
            Box Box3 = new Box();          // 声明 Box3,类型为 Box
            Box Box4 = new Box();
            double volume = 0.0;   // 体积

            // Box1 详述
            Box1.setLength(6.0);
            Box1.setBreadth(7.0);
            Box1.setHeight(5.0);

            // Box2 详述
            Box2.setLength(12.0);
            Box2.setBreadth(13.0);
            Box2.setHeight(10.0);

            // 使用重载的 ToString() 显示两个盒子
            Console.WriteLine("Box1: {0}", Box1.ToString());
            Console.WriteLine("Box2: {0}", Box2.ToString());
          
            // Box1 的体积
            volume = Box1.getVolume();
            Console.WriteLine("Box1 的体积: {0}", volume);

            // Box2 的体积
            volume = Box2.getVolume();
            Console.WriteLine("Box2 的体积: {0}", volume);

            // 把两个对象相加
            Box3 = Box1 + Box2;
            Console.WriteLine("Box3: {0}", Box3.ToString());
            // Box3 的体积
            volume = Box3.getVolume();
            Console.WriteLine("Box3 的体积: {0}", volume);

            //comparing the boxes
            if (Box1 > Box2)
                Console.WriteLine("Box1 大于 Box2");
            else
                Console.WriteLine("Box1 不大于 Box2");
            if (Box1 < Box2)
                Console.WriteLine("Box1 小于 Box2");
            else
                Console.WriteLine("Box1 不小于 Box2");
            if (Box1 >= Box2)
                Console.WriteLine("Box1 大于等于 Box2");
            else
                Console.WriteLine("Box1 不大于等于 Box2");
            if (Box1 <= Box2)
                Console.WriteLine("Box1 小于等于 Box2");
            else
                Console.WriteLine("Box1 不小于等于 Box2");
            if (Box1 != Box2)
                Console.WriteLine("Box1 不等于 Box2");
            else
                Console.WriteLine("Box1 等于 Box2");
            Box4 = Box3;
            if (Box3 == Box4)
                Console.WriteLine("Box3 等于 Box4");
            else
                Console.WriteLine("Box3 不等于 Box4");

            Console.ReadKey();
        }
    }
}
运行结果如下:

Box1: (6, 7, 5)
Box2: (12, 13, 10)
Box1 的体积: 210
Box2 的体积: 1560
Box3: (18, 20, 15)
Box3 的体积: 5400
Box1 不大于 Box2
Box1 小于 Box2
Box1 不大于等于 Box2
Box1 小于等于 Box2
Box1 不等于 Box2
Box3 等于 Box4