在C#中不可以继承多个基类,但是可以实现多个接口。但是当实现的不同接口中拥有相同名称的方法时,我们就必须使用限定的完全名称来在类中实现接口的方法,比如:


























在上面的代码中,两个接口IMySQL、IOracle有一个相同名称的方法GetConnStr,当类DB继承这两个接口时,必须使用完全限定名称来实现,也就是“接口名.方法名”。代码中的IMySQL.GetConnStr()和IOracle.GetConnStr()分别是接口IMySQL和IOracle中GetConnStr方法的实现(显式接口继承),而第三个GetConnStr方法则与两个接口没有任何关系(如果删除IMySQL.GetConnStr方法,第三个GetConnStr方法则成为IMySQL接口的实现方法)。
注意在两个显式接口成员实现的方法前面并没有public或private之类的访问限定符,这是因为有时候它们是public,有时候又是private,为什么这样说呢,请先看下例:













在此的第一个GetConnStr方法调用(connectionString = db.GetConnStr())实际上是调用了开始代码段中的第三个GetConnStr方法,即与任何接口无关的那个方法。在这个调用发生时,两个接口的GetConnStr方法是私有的(private),继承接口的类的实例并不能调用接口的方法。而当类的实例被转化成接口的类型时,GetConnStr方法成为了公开方法(public)。
接口的灵活性也会伴随着编译时类型安全的代价,因为很多的接口都接受System.Object类型的参数或者返回一个System.Object类型的值,比如常用的IComparable接口:






当我们定义一个值类型实现IComparable接口的CompareTo方法时:












然后调用这个类型的CompareTo方法:








上面这段代码中声明了一个Object类型的对象o,然后调用ValueType的CompareTo方法来接受o进行比较,这在编译期间没有任何错误发生,但是当运行时就会出现类型转换错误,这是因为o并不是ValueType类型,并没有一个x的字段。
CLR提供的显式接口成员实现可以帮助我们在编译时获得错误提示,从而避免程序运行后发生错误,提高类型安全,请看下面代码:



















在这段代码中提供了两个版本的CompareTo方法,第二个就是我们前面提到过的显式接口成员实现,让我们来看这样做的好处:









在第一次调用(n = vt1.CompareTo(vt2))中,使用的是接受ValueType类型参数的CompareTo方法,这样CLR就会在编译时进行类型检查,保证了类型安全,而之后的n = vt2.CompareTo(new Object());则会碰到编译时错误。如果我们想调用接受Object类型参数的CompareTo方法,就必须获得IComparable类型的一个引用,所以在最后一句中我们进行了类型转换并调用CompareTo方法。但是在最后一次的调用中vt1首先被装箱转换成IComparable类型,接下来因为IComparable.CompareTo方法接受Object类型参数,所以vt2被装箱转换成Object类型。
综上所述,显式接口成员实现帮助我们增强类型安全(无论是对值类型还是引用类型),对于值类型,还可以避免装箱操作,减少性能损耗。