有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成把两个整数加到一起的代码。 当编译器发现两个string类型的实例使用+操作符的时候,编译器会生成把两个字符串连接到一起的代码。那么编译器怎么就会知道这样做呢?如何进行操作符重载呢?

操作符重载

有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成把两个整数加到一起的代码。

当编译器发现两个string类型的实例使用+操作符的时候,编译器会生成把两个字符串连接到一起的代码。那么编译器怎么就会知道这样做呢?如何进行操作符重载呢?

下面C#代码展示了一个类中如何进行操作符重载:

namespace DoNet.Seven.ConsoleApplicationTest
{
class Program
{
static void Main(string[] args)
{
rational r1 = new rational(10);
rational r2 = new rational(5);
rational r3= r1 + r2;
Console.WriteLine(r3.Value);
Console.ReadKey(); }
}
//有理数
public sealed class rational
{
private int _value = 0; public int Value
{
get { return _value; }
set { _value = value; }
}
public rational(int value)
{
this._value = value;
} public rational()
{ }
public static rational operator+(rational num1,rational num2)
{
rational result = new rational(num1.Value+num2.Value);
return result;
} }
}

运行代码输入结果是15

用IL工具看下编译器生成的代码如下:

1、首先CLR规范要求操作符重载方法必须是public和static方法。另外,C#编译器要求操作符重载方法至少有一个参数的类型与当前定义的这个方法的类型相同。之所以这样做,

是为了是编译器能在合理的时间内找到要绑定的操作符方法。

2、编程语言的编译器看到源码中出现一个+操作符时,会检查是否有一个操作数的类型定义了一个名为op_Addtion的specialname方法,而且该方法的参数兼容于操作数的类型,

如果存在这样的一个方法,编译器就生成调用它的代码。如果不存在这样的一个方法,就生成一个编译错误。

3、对于其它操作符编译之后对应的方法如下表所示(左边是一元操作符,右边是二元操作符)

                                

转换操作符

当设计一个类型时应该考虑到和其它类型之间的转换,这个其实很重要,将对我们的编码有很大的好处,就像每个类型都会有的一个方法Tostring()一样,我们定义一个int类型,可以很方便的用tostring()方法把

int转换为string,当然也可以转换为其它类型。就像上面的rational一样,如果能将一个int或者double转换为一个rational,就会很方便,反之亦然。

 //有理数
public sealed class rational
{
private int _value = 0; public int Value
{
get { return _value; }
set { _value = value; }
}
public rational(int value)
{
this._value = value;
} public rational(double value)
{
this._value =(int)value;
}
public rational()
{ } public int ToInt()
{
return _value;
}
public double ToDouble()
{
return (double)_value;
}
public static rational operator+(rational num1,rational num2)
{
rational result = new rational(num1.Value+num2.Value);
return result;
} }

1、调用这些构造器和方法,开发人员可以很方便的将int和double对象转换成rational对象,这将给编程工作带来很多方便。设计类型时,应该认真考虑类型需要支持的转换构造器和方法。

2、int i=10;long j=i;这样的代码我们经常会看到,那么从int类型到long类型的转换为什么就可以隐士的进行呢?这就涉及到了我们的转换操作符,下面我们也为rational定义几个转换操作符。

namespace DoNet.Seven.ConsoleApplicationTest
{
class Program
{
static void Main(string[] args)
{
int n = 10;
rational r1 = n;
double d=(double)r1; Console.WriteLine(r1.Value);
Console.WriteLine(d.ToString());
Console.ReadKey(); }
}
//有理数
public sealed class rational
{
private int _value = 0; public int Value
{
get { return _value; }
set { _value = value; }
}
public rational(int value)
{
this._value = value;
} public rational(double value)
{
this._value =(int)value;
}
public rational()
{ } public int ToInt()
{
return _value;
}
public double ToDouble()
{
return (double)_value;
}
public static rational operator+(rational num1,rational num2)
{
rational result = new rational(num1.Value+num2.Value);
return result;
} public static implicit operator rational(int value)
{
return new rational(value);
}
public static implicit operator rational(double value)
{
return new rational(value);
}
public static explicit operator int(rational value)
{
return value.ToInt();
}
public static explicit operator double(rational value)
{
return value.ToDouble();
} }
}

输出的结果是10、10。 我们可以在rational、int、double之间来回转换,是不是觉得挺方便的,在这个过程中,编译器又帮我们做了什么呢?

在C#中,implicit关键字告诉编译器隐式转换时候来调用该方法,相反,explicit关键字告诉编译器只有在发现了显示转型时,才调用该方法。

在implicit或explicit关键字之后,要指定operator关键字告诉编译器该方法是一个转换操作符。在operator之后,指定对象要转换成什么类型。在圆括号内,则指定要从什么类型转换。

C#编译器检测到代码中的转型,并内部生成IL代码来调用rational类型定义的转换操作符方法,如果用反编译器看的话可以发现,转换操作符方法会生成下面这样的代码:

结论

不论是操作符重载还是转换操作符,都是在设计类型是考虑到我们编码方便而设计的,下面我们看下C#中decimal类型中的定义。

原文来源:https://www.cnblogs.com/skm-blog/p/4229487.html

(二) operator、explicit与implicit 操作符重载的更多相关文章

  1. (一) operator、explicit与implicit 操作符重载

                               原文地址:  Click Here 操作符重载必须用public static 应为操作符是用来操作实例的. operator operator ...

  2. HDU——1005Number Sequence(模版题 二维矩阵快速幂+操作符重载)

    Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  3. C#的关键字Explicit 和 Implicit

    一.explicit和implicit explicit 关键字用于声明必须使用强制转换来调用的用户定义的类型转换运算符:implicit 关键字用于声明隐式的用户自定义的类型转换运算符. 总结来说: ...

  4. C++一些注意点之操作符重载

    重载操作符需要注意 (1)重载操作符必须具有一个类类型操作数.不能重载内建类型的操作符. operator +(int,int);//这个是错误的,都为内建类型 operator +(int,clas ...

  5. C++解析(17):操作符重载

    0.目录 1.操作符重载 2.完善的复数类 3.小结 1.操作符重载 下面的复数解决方案是否可行? 示例1--原有的解决方案: #include <stdio.h> class Compl ...

  6. C++中操作符重载的概念

    1,下面的复数解决方案是否可行? 1,代码示例: class Comples { public: int a; int b; }; int main() { Complex c1 = {, }; Co ...

  7. [置顶] operator overloading(操作符重载,运算符重载)运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy)

    operator overloading(操作符重载,运算符重载) 所谓重载就是重新赋予新的意义,之前我们已经学过函数重载,函数重载的要求是函数名相同,函数的参数列表不同(个数或者参数类型).操作符重 ...

  8. C++ operator overload -- 操作符重载

    C++ operator overload -- 操作符重载 2011-12-13 14:18:29 分类: C/C++ 操作符重载有两种方式,一是以成员函数方式重载,另一种是全局函数. 先看例子 # ...

  9. 21.C++- "++"操作符重载、隐式转换之explicit关键字、类的类型转换函数

    ++操作符重载 ++操作符分为前置++和后置++,比如: ++a;  a++; ++操作符可以进行全局函数或成员函数重载 重载前置++操作符不需要参数 重载后置++操作符需要一个int类型的占位参数 ...

随机推荐

  1. java继承基础内容

    1 /* 2 * 继承的好处: 3 * 1,提高了代码的复用性. 4 * 2,让类与类之间产生了关系,给第三个特征多态提供了前提. 5 * 6 * 7 * java中支持单继承.不直接支持多继承,但对 ...

  2. vue开源项目有点全

    目录 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 UI组件 element ★31142 - 饿了么出品的Vue2的web UI工具套件 Vux ★14104- 基于Vue和 ...

  3. 负载均衡的比例(权重,ip_hash,轮询)

    目录 一:负载均衡的比例 1.轮询 2.权重 3.ip_hash 二:测试轮询 1.测试 2.重启 3.网址测试 三:测试ip_hash 一:负载均衡的比例 1.轮询 # 默认情况下,Nginx负载均 ...

  4. Mongodb全备+增备+oplog恢复误删数据

    此时测试表中有7条数据,做个全备. 全备: mongodump --host=192.168.43.43 --port=37017 --oplog --out=/opt/mongo/fullbacku ...

  5. Basler相机启动问题xml读取出错

    切记!同一张网卡上多网口分别连多相机的时候,不要用同一个网段!!很容易出错!

  6. HowToDoInJava Java 教程·翻译完成

    原文:HowToDoInJava 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远. ApacheCN 学习资源 目录 核心 Java 教程 什 ...

  7. linux中shell变量$#等的释义

    linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: 1. $$ Shell本身的PID(ProcessID) 2. $! Shell最后运行的后台Process的PID 3 ...

  8. JSP中的请求转发与重定向

    在说请求转发和重定向之前,得了解下JSP九大内置对象中的response和request response:将服务器端数据发送到客户端,可通过在客户端浏览器中显示,用户浏览页面的重定向以及在客户端创建 ...

  9. FastJSON解析Json字符串(反序列化为List、Map)

    在日常开发与数据库打交道的时候,常有以Json格式的字符串存储到数据库的情况,当在Java程序中获取到对应的Json格式的String字符串后,如何才能转换为我们想要的数据格式(比如转换成Java中的 ...

  10. docker基础——3.存储卷

    把宿主机的目录或文件链接到容器的目录或文件,可以避免写时复制对高I/O操作的影响,也避免容器销毁时数据丢失. 1. 只指定容器的目录位置,-v docker run -it --name bbox1 ...