《C#图解教程》读书笔记之六:接口和转换
本篇已收录至《C#图解教程》读书笔记目录贴,点击访问该目录可获取更多内容。
一、接口那点事儿
(1)什么是接口?
一组函数成员而未实现的引用类型。只有类和结构能实现接口。
(2)从IComparable接口看接口实例:
假设有如下一段代码,它使用Array类的一个静态方法Sort对一个未排序的int类型数组进行排序,并输出排序后的结果。
using System; class Program
{
static void Main()
{
var myInt = new[] { , , , , }; // Create an array of ints. Array.Sort( myInt ); // Sort elements by magnitude. foreach ( var i in myInt ) // Print them out.
Console.Write( "{0} ", i );
}
}
Sort方法在int类型数组的排序工作上做的很好,但是如果我们尝试在自定义的类上使用就会发生异常,例如下面的MyClass类。
class MyClass
{
public int TheValue;
}
Sort为何不能对MyClass进行排序,原因在于:它不知道如何比较自定义对象及如何进行排序。Array类的Sort方法其实依赖于一个IComparable的接口,它声明在BCL中,包含唯一的CompareTo方法。它接收一个object类型的参数,可以匹配任何引用类型。
public interface IComparable
{
int CompareTo(object obj);
}
这下,我们知道了int类型默认实现了IComparable接口,而我们的MyClass则没有。因此,我们需要将MyClass实现这个IComparable接口。
class MyClass : IComparable
{
public int TheValue;
public int CompareTo( object obj )
{
MyClass mc = (MyClass) obj; if ( this.TheValue < mc.TheValue )
return -; if ( this.TheValue > mc.TheValue )
return ; return ;
}
}
现在,MyClass类实现了IComparable接口,它可以用于Sort方法了。
class Program
{
static void PrintOut( string s, MyClass[] mc )
{
Console.Write( s );
foreach ( var m in mc )
Console.Write( "{0} ", m.TheValue ); Console.WriteLine( "" );
} static void Main()
{
var myInt = new[] { , , , , }; MyClass[] mcArr = new MyClass[];
for ( int i = ; i < ; i++ )
{
mcArr[i] = new MyClass();
mcArr[i].TheValue = myInt[i];
} PrintOut( "Initial Order: ", mcArr ); Array.Sort( mcArr );
PrintOut( "Sorted Order: ", mcArr );
}
}
现在,一个完整的接口实例已经完毕。

(3)使用接口注意事项:
①声明接口时:不能包含:数据成员、静态成员;只能声明:方法、属性、事件、索引器;
TIP:接口允许有任何的访问修饰符,但是接口成员是隐式public的,不允许有任何的访问修饰符,包括public。

②实现接口时:在基类列表中包括接口名称;为每一个接口的成员实现接口;
(4)接口是一种引用类型:我们不能直接通过类或对象的成员访问接口,然而,我们可以通过把类对象转换成接口类型来获取指向接口的引用。一旦有了接口的引用,我们就可以使用点号来调用接口的方法。
using System; interface IIfc1
{
void PrintOut( string s );
} class MyClass : IIfc1
{
public void PrintOut( string s )
{
Console.WriteLine( "Calling through: {0}", s );
}
} class Program
{
static void Main()
{
MyClass mc = new MyClass();
mc.PrintOut( "object" ); IIfc1 ifc = (IIfc1) mc;
ifc.PrintOut( "interface" );
}
}
下面我们看看上面的代码在内存中的分配:

(5)接口和as运算符=>天生一对
在以往使用接口引用时,我们往往会使用强制类型转换,但强制类型转换会抛出异常(异常是指代码中的意外错误,它会严重降低代码速度)。如何避免这个问题,我们可以使用as运算符,在类对象未实现接口时不会抛出异常,只会返回null。

二、看我72变:转换
(1)本质:接受一个类型的值并使用它作为另一个类型的等价值的过程;

(2)转换分类:
①预定义的转换:数字、装箱/拆箱、引用转换;
数字类型的转换详见下图:

装箱/拆箱是一个比较重要的点,现在我们来看看:
装箱(boxing)是值类型->引用类型,本质其实是创建副本。装箱是一种隐式转换,它接收值类型的值,根据这个值在在堆上创建一个完整的引用类型对象并返回对象引用。

拆箱(unboxing)是引用类型->值类型,本质把装箱后的对象转换回值类型。拆箱是显示转换。

②用户自定义的转换:隐式和显示的自定义转换;
using System; class Person
{
public string Name;
public int Age; public Person( string name, int age )
{
Name = name;
Age = age;
} public static implicit operator int( Person p )
{
return p.Age;
} public static implicit operator Person( int i )
{
return new Person( "Nemo", i );
}
} class Program
{
static void Main()
{
Person bill = new Person( "bill", ); int age = bill;
Console.WriteLine( "Person Info: {0}, {1}", bill.Name, age ); Person anon = ;
Console.WriteLine( "Person Info: {0}, {1}", anon.Name, anon.Age );
}
}
(3)is运算符:
在转换过程中,有些转换是不成功的,并且会在运行时抛出一个InvalidCastException异常。我们可以使用is运算符来检查转换是否会成功,从而避免盲目地尝试转换。

本章思维导图

附件
思维导图(jpg、pdf以及mmap源文件)下载:http://pan.baidu.com/s/1qWNOGGW
《C#图解教程》读书笔记之六:接口和转换的更多相关文章
- C#图解教程读书笔记(第1章 C#和.net框架)
C#中的主要需要记住的基础概念 CLR公共语言运行库 CIL中间语言,所有的代码都会编译成中间语言. CLI公共语言基础结构 C#的优点 C#有自动垃圾回收机制
- C#图解教程读书笔记(第15章 委托)
委托是C#的一个很重要的知识点. 1.什么是委托 委托在我认为,就是一系列格式相同的方法列表,可能就是定义的名称不一致,参数.返回值等都是一样的. 2.如何声明委托 delegate void MyF ...
- C#图解教程读书笔记(第9章 语句)
文件头的Using是Using指令,不是using语句 using (TextWriter tw = File.CreateText("xixi.txt")) { tw.Write ...
- C#图解教程读书笔记(第8章 表达式和运算符)
表达式 字面量 整数字面量 字符字面量 字符串字面量 求值顺序 优先级 结合性 与C和C++不同,在C#中的数字不具有布尔意义. 各种运算符的作用(过) 用户定义类型转换 class XiXiInt ...
- C#图解教程读书笔记(第7章 类和继承)
1.所有的类都继承自object 2.如何隐藏基类的成员 要隐藏一个继承的数据成员,需要声明一个新的相同类型的成员,并使用相同的名称. 通过在派生类中声明新的带有相同签名的函数成员,可以隐藏或掩盖继承 ...
- C#图解教程读书笔记(第6章 类进阶)
类成员声明语句由下列部分组成:核心声明.一组可选的修饰符和一组可选的特性(attribute). [特性] [修饰符] 核心声明 修饰符: 如果有修饰符,必须放在核心声明之前. 如果有多个修饰符,要有 ...
- C#图解教程读书笔记(第5章 方法)
类型推断和var关键字 从C#3.0开始,可以在变量声明的开始部分的的位置使用新的关键字var. Var关键字并不是某种特别类型的符号.它只是句法上的速记,表示任何可以从初始化的右边推断出的类型. V ...
- C#图解教程读书笔记(第4章 类:基础)
类成员包括数据成员和函数成员. 和C/C++不同,C#在类型的外部不能声明全局变量,所有的字段都属于类型,而且必须在类型声明内部声明. 和C/C++不同,方法没有返回默认类型,所有方法必须包含返回类型 ...
- C#图解教程读书笔记(第3章 类型、存储及变量)
1.C#的中的数值不具有bool特性. 2.dynamic在使用动态语言编写的程序集时使用,这个不太明白,看到后面需要补充!! 动态化的静态类型 3.对于引用类型,引用是存放在栈中,而数据是存放在堆里 ...
- C#图解教程读书笔记(第2章 C#编程概述)
这章主要是一个对于C#程序的概括解释 和C/C++不同,不是用include声明引用的头文件,而是通过using的方式,声明引用的命名空间. 命名和C/C++类似,并且也是区分大小写的,这件事情在VB ...
随机推荐
- 基类用的this指针
结论:基类构造函数中的this指针指向的是派生类的对象 测试代码: #include <iostream> using namespace std; class father; fathe ...
- 迅雷VIP帐号获取小工具
自己写的迅雷vip帐号获取工具,主要是熟悉一下正则表达式 下载地址: 迅雷VIP获取工具 另附vip防踢补丁,不能使用最新迅雷,我使用的是迅雷尊享版2.0.12.258,使用了一段时间,至少没被踢出来 ...
- PhoneGap--001 入门 安装
PhoneGap 百度百科 PhoneGap 中文网 3.0 安装使用 今天也配置好phonegap3.0 android开发环境了,操作系统是win7,就楼主文章做些补充. 我是按phonegap官 ...
- vim c++补全
弄了个vim对c++的补全,主要参考自: http://vim.wikia.com/wiki/C%2B%2B_code_completion 首先确定vim编辑.cc或者.cpp文件时当前自动补全 ...
- Some About Spring
什么是Spring:Spring是一个从实际开发中抽取出来的框架,它对代码中需要重复解决的步骤抽象成为了一个框架.留给开发者的仅仅是与特定应用相关的部分,大大提高了企业应用的开发效率.例外.Sprin ...
- iOS emoji表情转码 或者判断
如果项目中有评论或者信息恢复的地方,往往会用到emoji,有时候如后台不支持emoji,就会显示乱码错误,我们可以把emoji转成unicode编码或者utf8编码格式传给服务器.当然如果后台服务器接 ...
- sikuli实战记录
最近,为了解放运营人力,需要对某国企的系统进行自动化操作.该系统使用的是https,需要加载证书,而且非得用IE才行,firefox无法正常的加载证书.而selenium启动的IE是纯净的,不会加载任 ...
- zabbix微信告警(虚拟机脚本测试成功,zabbix上收不到信息)
前言: 使用zabbix直接运行脚本又可以正常接收.但是登录zabbix web界面,测试! 动作显示已送达,但是微信并没有收到信息! 解决: 添加脚本参数,因为不添加脚本参数,调用不了你这个脚本 ...
- CentOS 7 关闭防火墙
CentOS 7.0默认使用的是firewall作为防火墙 直接关闭防火墙 systemctl stop firewalld.service #停止firewall systemctl disable ...
- 关于angular的一些新手容易忽略的小知识点
1.解决页面刚加载时使用{{name}}这种方式绑定数据会有一瞬间的表达式显示的问题 方法一: 使用ng-bind来绑定数据, 方法二: 添加ng-cloak指令:如 <div ng-app ...