一、隐式转换和显式转换
直接把类实例委派给接口变量被称作“隐式转换”:
obj=new MyClass();
obj.Method1();
当使用隐式转换时,编译器会强制类型安全,如果类MyClass没有实现接口IMyInterface,编译器会拒绝生成代码并产生一个编译时错误。编译器之所以这样执行是因为它可以读取类MyClass的元数据并预知该类是否继承于接口IMyInterface。但是,有一些转换不可以使用隐式转换。这种情况下可以使用显式转换。即从一种类型到另一种类型:
obj=(IMyInterface)new MyClass();
obj.Method1();
但是,切记对接口的显式转换是建立在牺牲类型安全之上的。即使类MyClass不支持接口IMyInterface,编译器仍会编译通过代码,.Net会在转换失败时抛出一个运行时异常。
{
object GetObject();
}
IClassFactory factory;
/* Some code to initialize the class factory */
IMyInterface obj;
obj=(IMyInterface)factory.GetObject();
obj.Method1();
另一个隐式转换不适用的例子是当要使用一个接口的实现类,而这个类是该类同样支持的另一个接口的引用。即使客户端通过隐式转换得到第一个接口,它仍旧需要通过显式转换得到第二个:
{
void Method1();
void Method2();
}
public interface IMyOtherInterface
{
void Method3();
}
public class MyClass:IMyInterface,IMyOtherInterface
{
public void Method1()
{}
public void Method2()
{}
public void Method3()
{}
}
//Client-Side code;
IMyInterface obj1;
IMyOtherInterface obj2;
obj1=new MyClass();
obj1.Method1();
obj2=(IMyOtherInterface)obj1;
obj2.Method3();
IMyInterface obj2;
/* Some code to initialize obj1 */
obj2 = obj1 as IMyInterface;
if (obj2 != null)
{
obj2.Method1();
}
else
{
//Handle error in expected interface
}
总之,应当总是在客户端进行防御式编程(例如as操作符)。不能断言一个类一定支持一个接口——这样可以同时兼顾强健的错误处理及接口和实现分离,无论服务端是否使用显式接口实现。养成在客户端通过接口调用服务和强制隔离的习惯。