对于操作符,我们并不陌生,例如+,-,*,%等二元操作符,以及++,!等一元操作符。但是对于非基元类型,我们需要通过一些自定义方法才能使用这些操作符。今天主要和大家分享关于操作符重载和转换操作符的知识。


一、操作符重载方法

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)-操作符的更多相关文章

  1. CLR 初步

    1. 源代码编译为托管模块 程序在.NET框架下运行,首先要将源代码编译为 托管模块.CLR是一个可以被多种语言所使用的运行时,它的很多特性可以用于所有面向它的开发语言.微软开发了多种语言的编译器,编 ...

  2. CLR via C#(03)- 对象创建和类型转换

    一. 创建对象 CLR要求用new操作符创建对象,这个操作符在编译时产生的IL指令为newobj.例如: Student XiaoJing=new Student(“XiaoJing”,”1986”) ...

  3. CLR via C#深解笔记四 - 方法、参数、属性

    实例构造器和类(引用类型) 构造器(constructor)是允许将类型的实例初始化为良好状态的一种特殊方法.构造器方法在“方法定义元数据表”中始终叫.ctor. 创建一个引用类型的实例时: #1, ...

  4. C#构造函数、操作符重载以及自定义类型转换

    构造器 构造器(构造函数)是将类型的实例初始化的特殊方法.构造器可分为实例构造器和类型构造器,本节将详细介绍有关内容. 实例构造器 顾名思义,实例构造器的作用就是对类型的实例进行初始化.如果类没有显示 ...

  5. CLR via c#读书笔记五:方法

    注:书本第8章:方法 实例构造器和类(引用类型) 构造器方法在“方法定义元数据表”中始终叫做.ctor(constructor的简称). 构造引用类型的对象,在调用类型的实例构造器之前,为对象分配的内 ...

  6. CLR - 设计类型

    前言 好记性不如烂“笔头”系列... 目录 类型基础 基元类型.引用类型和值类型 类型与成员 常量与字段 方法 类型基础 “运行时”要求每个类型最终都从System.Object 类型派生. 由于所有 ...

  7. 应用服务器GC回收常见问题总结

    近一段时间多次发现因GC问题造成系统性能问题(应用服务间歇性响应缓慢.应用服务器CPU占用较高等),在此总结一下: 1.代码中直接调用GC.Collect() 2.字符串等操作频繁的内存申请 3.频繁 ...

  8. 记一次 .NET 某工控自动化控制系统 卡死分析

    一:背景 1. 讲故事 前段时间遇到了好几起关于窗体程序的 进程加载锁 引发的 程序卡死 和 线程暴涨 问题,这种 dump 分析难度较大,主要涉及到 Windows操作系统 和 C++ 的基础知识, ...

  9. 记一次 .NET 某数控机床控制程序 卡死分析

    一:背景 1. 讲故事 前段时间有位朋友微信上找到我,说它的程序出现了卡死,让我帮忙看下是怎么回事? 说来也奇怪,那段时间求助卡死类的dump特别多,被迫训练了一下对这类问题的洞察力 ,再次声明一下, ...

随机推荐

  1. UIMenuController使用

    - (void)bubbleDidLongPress:(UILongPressGestureRecognizer *)gestureRecognizer { if(gestureRecognizer. ...

  2. 在 2017 年将会更加流行的 6 个 Web 开发趋势

    2016即将过去,2017就要来临. 前阵子看到很多对2016前端领域的总结,也是有人欢喜有人忧啊. 转发了这一篇2017web的发展趋势.那么到底会是怎么样的一个发展趋势的,只好拭目以待了. 201 ...

  3. [codevs1001]舒适的路线

    [codevs1001]舒适的路线 试题描述 Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光.Z小镇附近共有N(1<N≤500)个景点(编号为1,2,3,-,N),这些景点被M(0 ...

  4. Kali Linux渗透基础知识整理(二)漏洞扫描

    Kali Linux渗透基础知识整理系列文章回顾 漏洞扫描 网络流量 Nmap Hping3 Nessus whatweb DirBuster joomscan WPScan 网络流量 网络流量就是网 ...

  5. Bootstrap IIFE

    在Bootstrap源码(具体请看<Bootstrap源码解析>)和其他jQuery插件经常看到如下的写法: +function ($) { }(window.jQuery); 这种写法称 ...

  6. iframe自适应宽度

    <iframe id="course_content" style="width:100%;margin:5px 0 0;" scrolling=&quo ...

  7. [20160725]MyComparableTest

    知识点: 1.Collections的使用. 2.自定义类泛型的使用. 3.自定义类,toString();equals();hashCode()方法的重写. import java.util.*; ...

  8. 【转载】通过JDBC对MySQL数据库的增删改查

    通过JDBC进行简单的增删改查(以MySQL为例) 目录 前言:什么是JDBC 一.准备工作(一):MySQL安装配置和基础学习 二.准备工作(二):下载数据库对应的jar包并导入 三.JDBC基本操 ...

  9. ACM/ICPC 之 DP-基因相似度(POJ1080-ZOJ1027)

    题意:两端基因片段,各有明确的碱基序列,现有一个碱基匹配的相似度数组,设计程序使得该相似度最大. //POJ1080-ZOJ1027 //题解:将s1碱基和s2碱基看做等长,添加一个碱基为'-',即每 ...

  10. ffmpeg-20160813-bin.7z

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...