CLR via C#(08)-操作符
对于操作符,我们并不陌生,例如+,-,*,%等二元操作符,以及++,!等一元操作符。但是对于非基元类型,我们需要通过一些自定义方法才能使用这些操作符。今天主要和大家分享关于操作符重载和转换操作符的知识。
一、操作符重载方法
CLR并不知道操作符,操作符重载对于它来说只是一些方法而已。但是CLR规定了语言应该如何公开操作符重载,每种编程语言自行决定是否支持操作符重载。
定义操作符重载方法注意两点:
- CLR规范要求操作符重载方法必须是 public static 类型。
- C#要求操作符重载方法必须有一个参数的类型和当前定义这个方法的类型相同。否则会产生编译错误

操作符重载实例
我们为非基元类型Complex重载操作符 “+”.

定义之后,可以使非基元类型Complex方便的进行+操作。


Sepecialname标记
ILDaxm.exe查看Complex类的元数据,发现产生了一个op_Addition项。如果重载其他操作符,也会自动产生相应的specialname标记。

在编译过程中,当代码中出现“+”操作符时,编译器会自动检查op_Addition的specialname标记,并且检测参数类型兼容性。
下面两个表是C#允许重载的一元操作符和二元操作符。简单了解一下就好,没必要强记。


二、转换操作符方法
当两个非基元类型的实例需要相互转换时,我们需要定义转换操作符方法。转换操作符是指将对象从一个类型转换成另一个类型的方法。
两大规定
- CLR要求转换操作符重载方法必须是public static 方法。
- C#要求参数类型和返回类型必须至少有一个与定义转换方法的类型相同。
另外,为了完成转换操作,我们应该在类型内定义两类方法:
- 实例公共构造器。参数是源类型的实例
- 无参公共实例方法Toxxx。该方法将定义类型的实例转换成xxx类型。
转换操作符例子
为Rational(有理数)类型定义转换操作符,方便与Int32类型实例进行相互转换。

implicit和explicit
在这个例子中,我们定义了两种转换操作符方法:implicit关键字表示在源代码中不需要进行显式转型;explicit关键字表示进行显式转型时才调用该方法。Operator关键字表明该方法是一个转型操作符。
使用ILDasm.exe查看,

可以发现添加了两个方法:op_Explicit和op_Implicit。只有当转换后不丢失精度的前提下,才能进行隐式转换;如果会发生精度丢失,则只能定义为显式转换。
定义完成之后我们就可以方便的进行转型调用了。
static void Main(string[] args)
{
Rational r1 = 5; // 隐式转换
Int32 x = (Int32)r1; // 显示转换
}
关于重载
在上面的例子中,实际上一个类型经常会和多个类型实例进行转换操作,此时就需要再定义其他转换操作符,例如public static explicit operator Single(Rational r),也就是进行方法重载。对于重载,我们并不陌生,特殊之处在于这两个explicit重载方法仅仅通过返回值类型不同来区分的。
CLR允许定义多个同名方法,只要每个方法的参数或者返回值类型有所区别即可。但是在C#判断方法的唯一性时,除了方法名称外只考虑参数的区别,而忽略掉方法的返回类型。所以,上面的两个重载方法仅有返回类型的差异实际上是C#放宽限制的特例。
CLR via C#(08)-操作符的更多相关文章
- CLR 初步
1. 源代码编译为托管模块 程序在.NET框架下运行,首先要将源代码编译为 托管模块.CLR是一个可以被多种语言所使用的运行时,它的很多特性可以用于所有面向它的开发语言.微软开发了多种语言的编译器,编 ...
- CLR via C#(03)- 对象创建和类型转换
一. 创建对象 CLR要求用new操作符创建对象,这个操作符在编译时产生的IL指令为newobj.例如: Student XiaoJing=new Student(“XiaoJing”,”1986”) ...
- CLR via C#深解笔记四 - 方法、参数、属性
实例构造器和类(引用类型) 构造器(constructor)是允许将类型的实例初始化为良好状态的一种特殊方法.构造器方法在“方法定义元数据表”中始终叫.ctor. 创建一个引用类型的实例时: #1, ...
- C#构造函数、操作符重载以及自定义类型转换
构造器 构造器(构造函数)是将类型的实例初始化的特殊方法.构造器可分为实例构造器和类型构造器,本节将详细介绍有关内容. 实例构造器 顾名思义,实例构造器的作用就是对类型的实例进行初始化.如果类没有显示 ...
- CLR via c#读书笔记五:方法
注:书本第8章:方法 实例构造器和类(引用类型) 构造器方法在“方法定义元数据表”中始终叫做.ctor(constructor的简称). 构造引用类型的对象,在调用类型的实例构造器之前,为对象分配的内 ...
- CLR - 设计类型
前言 好记性不如烂“笔头”系列... 目录 类型基础 基元类型.引用类型和值类型 类型与成员 常量与字段 方法 类型基础 “运行时”要求每个类型最终都从System.Object 类型派生. 由于所有 ...
- 应用服务器GC回收常见问题总结
近一段时间多次发现因GC问题造成系统性能问题(应用服务间歇性响应缓慢.应用服务器CPU占用较高等),在此总结一下: 1.代码中直接调用GC.Collect() 2.字符串等操作频繁的内存申请 3.频繁 ...
- 记一次 .NET 某工控自动化控制系统 卡死分析
一:背景 1. 讲故事 前段时间遇到了好几起关于窗体程序的 进程加载锁 引发的 程序卡死 和 线程暴涨 问题,这种 dump 分析难度较大,主要涉及到 Windows操作系统 和 C++ 的基础知识, ...
- 记一次 .NET 某数控机床控制程序 卡死分析
一:背景 1. 讲故事 前段时间有位朋友微信上找到我,说它的程序出现了卡死,让我帮忙看下是怎么回事? 说来也奇怪,那段时间求助卡死类的dump特别多,被迫训练了一下对这类问题的洞察力 ,再次声明一下, ...
随机推荐
- iOS开发——UI基础-UIScrollView
一.UIScrollView使用的步骤 1.创建UIScrollView 2.将需要展示的内容添加到UIScrollView中 3.设置UIScrollView的滚动范围 (contentSize) ...
- php服务端写日志文件
1.需求 在服务端记录日志 2.基础版 最基础的文件读写,(要注意window和linux的换行符,window是\r\n,linux是\n),这里就写入一个时间. <?php $handle ...
- jQuery中的checkbox问题
一开始的代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...
- SSH-Struts第四弹:Struts2学习过程中遇到的问题
1.2014-03-27 22:03:10 问题点:在struts.xml中进行常量的配置:devMode=true不起作用,还是必须重新启动tomcat,才能使修改过的struts.xml和Acti ...
- OpenCV图像的二值化
图像的二值化: 与边缘检测相比,轮廓检测有时能更好的反映图像的内容.而要对图像进行轮廓检测,则必须要先对图像进行二值化,图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出 ...
- We will be discontinuing the Nitrous Development Platform and Cloud IDE on November 14th, 2016.
我表示我很难过 Nitrous We will be discontinuing the Nitrous Development Platform and Cloud IDE on November ...
- POJ 1258
http://poj.org/problem?id=1258 今天晚上随便找了两道题,没想到两道都是我第一次碰到的类型———最小生成树.我以前并没有见过,也不知道怎么做,然后就看书,思路很容易理解 但 ...
- CentOS卸载OpenJDK并安装Sun JDK
第一步:查看Linux自带的JDK是否已安装 (卸载centOS已安装的1.4) 安装好的CentOS会自带OpenJdk,用命令 java -version ,会有下面的信息: java versi ...
- c++ macro
C++ Code 12345678910111213141516171819202122232425262728293031 /* version: 1.0 author: hellogise ...
- ios 多线程必读内容 :锁
大学时的生产者消费者问题还记得吗?ios中的锁,请阅读以下官方文档,虽然是英文的,但是说的非常准确: Threading Programming Guide 中的 Synchronization ht ...