本篇已收录至《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

作者:周旭龙

出处:http://www.cnblogs.com/edisonchou/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

《C#图解教程》读书笔记之六:接口和转换的更多相关文章

  1. C#图解教程读书笔记(第1章 C#和.net框架)

    C#中的主要需要记住的基础概念 CLR公共语言运行库 CIL中间语言,所有的代码都会编译成中间语言. CLI公共语言基础结构 C#的优点 C#有自动垃圾回收机制

  2. C#图解教程读书笔记(第15章 委托)

    委托是C#的一个很重要的知识点. 1.什么是委托 委托在我认为,就是一系列格式相同的方法列表,可能就是定义的名称不一致,参数.返回值等都是一样的. 2.如何声明委托 delegate void MyF ...

  3. C#图解教程读书笔记(第9章 语句)

    文件头的Using是Using指令,不是using语句 using (TextWriter tw = File.CreateText("xixi.txt")) { tw.Write ...

  4. C#图解教程读书笔记(第8章 表达式和运算符)

    表达式 字面量 整数字面量 字符字面量 字符串字面量 求值顺序 优先级 结合性 与C和C++不同,在C#中的数字不具有布尔意义. 各种运算符的作用(过) 用户定义类型转换 class XiXiInt ...

  5. C#图解教程读书笔记(第7章 类和继承)

    1.所有的类都继承自object 2.如何隐藏基类的成员 要隐藏一个继承的数据成员,需要声明一个新的相同类型的成员,并使用相同的名称. 通过在派生类中声明新的带有相同签名的函数成员,可以隐藏或掩盖继承 ...

  6. C#图解教程读书笔记(第6章 类进阶)

    类成员声明语句由下列部分组成:核心声明.一组可选的修饰符和一组可选的特性(attribute). [特性] [修饰符] 核心声明 修饰符: 如果有修饰符,必须放在核心声明之前. 如果有多个修饰符,要有 ...

  7. C#图解教程读书笔记(第5章 方法)

    类型推断和var关键字 从C#3.0开始,可以在变量声明的开始部分的的位置使用新的关键字var. Var关键字并不是某种特别类型的符号.它只是句法上的速记,表示任何可以从初始化的右边推断出的类型. V ...

  8. C#图解教程读书笔记(第4章 类:基础)

    类成员包括数据成员和函数成员. 和C/C++不同,C#在类型的外部不能声明全局变量,所有的字段都属于类型,而且必须在类型声明内部声明. 和C/C++不同,方法没有返回默认类型,所有方法必须包含返回类型 ...

  9. C#图解教程读书笔记(第3章 类型、存储及变量)

    1.C#的中的数值不具有bool特性. 2.dynamic在使用动态语言编写的程序集时使用,这个不太明白,看到后面需要补充!! 动态化的静态类型 3.对于引用类型,引用是存放在栈中,而数据是存放在堆里 ...

  10. C#图解教程读书笔记(第2章 C#编程概述)

    这章主要是一个对于C#程序的概括解释 和C/C++不同,不是用include声明引用的头文件,而是通过using的方式,声明引用的命名空间. 命名和C/C++类似,并且也是区分大小写的,这件事情在VB ...

随机推荐

  1. 我的Windows软件清单

    1.evernote : 没错,这篇笔记就是用 evernote 写的,说实话,这款产品我只是在PC上用,虽然手机上也下了,不过似乎体验不是很好(可能是屏幕不够大的原因),用得非常少.这个软件里面可以 ...

  2. postgresql数据迁移

    postgresql从库故障准备新库 1,创建用户[root@localhost home]# userdel postgres[root@localhost home]# groupdel post ...

  3. Python中获取异常(Exception)信息

    异常信息的获取对于程序的调试非常重要,可以有助于快速定位有错误程序语句的位置.下面介绍几种python中获取异常信息的方法,这里获取异常(Exception)信息采用try...except...程序 ...

  4. linux下搭建nagios

    配置环境:1)CentOS 6.5 作为监控主机,IP:10.0.0.30(根据自己公司需要改变) 2)客户机: windows server  2008R2 , windows 7, windows ...

  5. log4j向oracle中插入一条系统当前时间的sql语句

    配置log4j,要向oracle插入一条系统当前时间的sql语句,按网上查找的总是出现各种各样的报错,最后总结出的写法是: ### shezhi### log4j.rootLogger = debug ...

  6. PD4F将HTML转换为PDF乱码问题

    修改pd4fonts.properties文件如下: KaiTi_GB2312=SIMKAI.TTFSimSun=SIMKAI.TTF

  7. DBCP配置数据库连接乱码问题

    driverClassName = com.mysql.jdbc.Driver url = jdbc:mysql:///bigdata username = root password = 82371 ...

  8. JDBC小工具--TxQueryRunner及其单元测试

    1.TxQueryRunner的简介(需要相关jar包的请留言) TxQueryRunner类是common-dbutils下QueryRunner的子类,是用来简化JDBC操作的,所以要导入comm ...

  9. 今天我们要说的画一个三角形,恩,画一个三角形,第一种呢是利用我们的html标签结合css来实现;而第二种方法就就是我们的html5新增的一个标签canves,这个canves就是网页画幕,那么顾名思义就是在网页里建造一个画板,用来画画,好,那接下来就和我一起去看看吧!

    第一种方法:利用我们的html标签结合css来实现 span{ width:0px; height:0px; border-width:7px; border-style:solid; border- ...

  10. template学习一函数模板

    要点: 1.模板参数在实体化的时候不能自动类型转换,只有非模板函数才可以 例如: int max(int,int); template <class T> T max(T,T); 在调用的 ...