WEB开发网
开发学院软件开发C语言 C#动静结合编程之一: 接口和委托的约束强度 阅读

C#动静结合编程之一: 接口和委托的约束强度

 2009-03-17 08:19:04 来源:WEB开发网   
核心提示: .NET2.0通过泛型集合增加了静态类型约束:B(){ List<string> lst = A(); foreach (string item in lst){ Console.WriteLine(item); }}这样,B再也不用担心lst内部存在非string类型的元素了

.NET2.0通过泛型集合增加了静态类型约束:

B(){
    List<string> lst = A();
    foreach (string item in lst){
        Console.WriteLine(item);
    }
}

这样,B再也不用担心lst内部存在非string类型的元素了,一切得益于泛型为A加上的静态类型约束。

约束有强弱

约束有强弱之分。越强的约束越安全,静态性越强,受编译器的支持越大;反之,越弱的约束,动态性越强,运行时灵活性越大。

接口和委托都是用于分离规范与实现从而达到面向抽象编程的重要手段,二者有共通之处,尤其单方法接口和委托更是如此。常常看到关于单方法接口和委托异同的讨论,不少朋友认为它们完全等价。其实,它们有明显不同的语法约束强度。接口是静态类型约束,而委托只是静态签名约束,二者的强度完全不同。换句话说,委托具有更多的协议性,只要是符合签名的方法或匿名委托,都可以被委托调用,而能被接口调用的对象必须实现该接口。

来看一个例子:需要编写一个类A,其内部需要日志功能;A采用IoC方式,不依赖于具体的Logger类,由使用者根据需要注入具体的实现;同时,A的使用者B,希望采用第三方的Logger类。

a. 基于接口的IoC

interface ILogger { void Write(string msg); }

class A{
    ILogger Logger { get; set; }
    void F() {}
}

class B{
    G(){
        A a = new A();
        a.Logger = new LogAdapter(); //注入依赖
        a.F();
    }
}

//对第3方Logger进行包装
class LogAdapter : ILogger{
    Write(string msg){//这里调用第3方的Logger类}
}

b. 基于委托的IoC

class A{
    Action<string> Logging { get; set; }
    void F() {}
}

class B{
    G(){
        A a = new A();
        a.Logging = delegate(string msg){ //调用第3方Logger类 };
        a.F();
    }
}

比较上面两个例子,我们就会发现委托比接口的约束要弱得多,使用起来灵活得多。基于接口的实现不得不增加一个Adapter去机械地适应接口的类型约束,而基于委托的实现只需要保证方法签名约束即可。

上面讨论接口与委托的语法约束强度,并不是对接口和委托的全方位比较,这里是希望大家能体会两种不同的OO多态哲学:接口的哲学是你继承什么你就是什么,委托的哲学是你能做什么你就是什么。这两种哲学反映在C#中就表现出接口的继承式约束的严谨但不灵活的静态特性,委托的灵活但不那么严谨的动态特性。这一点体悟对理解Duck Typing有很大的帮助。

后续

后续章节打算陆续介绍DuckTyping、泛型委托妙用、表达式树和lambda、C#4.0动态编程等相关内容,敬请关注,多谢批评!

修改历史:

1. 2009-03-11 初版

2. 2009-03-15 标题修改为“C#动静结合编程”;

根据读者点评,补充说明“动态”和“静态”的具体指什么;

补充对接口和委托的说明

系列文章:

C#动静结合编程之二: 两种哲学

上一页  1 2 

Tags:动静 结合 编程

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接