The wind call my name

用知识和思考来丈量世界
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

《Programming .Net Components》学习笔记(四)

Posted on 2007-05-03 08:31  徐鸿翼  阅读(698)  评论(0编辑  收藏  举报

三、显式实现泛型接口

与非泛型接口相同,泛型接口也可以显式实现:

    public class NumberList : IList<int>

    {

        void IList<int>.AddHead(int item)

        {...}

        void IList<int>.RemoveHead(int item)

        {...}

        void IList<int>.RemoveAll()

        {...}

}

需要注意的是显式实现中类型参数的指定。因为,譬如AddHead()方法不仅是泛型接口IList<T>的一个方法,确切地说应是一个类型参数为int的泛型接口方法。同样的,如果实现类本身是一个泛型类,则下边这种实现也是正确的:

    public class List<T> : IList<T>

    {

        void IList<T>.AddHead(T item)

        {...}

        //Rest of the implementation

}

当要在同一个类型里显式实现泛型类型的多个版本要特别注意,需要实现每个版本的方法:当让也可以隐式实现:

    public class List : IList<int>, IList<string>

    {

        public void AddHead(int item)

        {...}

        public void AddHead(string item)

        {...}

        public void RemoveAll()

        {...}

}

在这个例子中这样要比使用显式接口继承要好些。因为像RemoveAll()这样的方法可以在同一实现方法中实现IList<int>IList<string>。客户端对IList<int>,IList<string>都可以调用该方法:

IList<int> list = new List();

       list.RemoveAll();

但是,在实现同一泛型接口的多个类型参数版本时,往往不得不使用显式实现,否则会产生二义性。例如,如果IList<T>包含这样一个GetHead()方法:

    public interface IList<T>

    {

        void AddHead(T item);

        void RemoveHead(T item);

        void RemoveAll();

        T GetHead();

}

    public class List : IList<int>, IList<string>

    {

        int IList<int>.GetHead()

        {...}

        string IList<string>.GetHead()

        {...}

        // Rest of the implementation

}


四、泛型接口操作符

C#2.0有一个有趣的泛型接口的应用。在C#2.0中不可以对泛型参数使用像++=这样的操作符。像下边这样的代码就不会通过编译:

    public class Calculator<T>

    {

        public T Add(T argument1, T argument2)

        {

            return argument1 + argument2; //不会通过编译

        }

        //Rest of the methods

}

编译器不会知道客户端指定的类型参数是否支持+操作符,所以拒绝编译。不过那,可以通过使用泛型操作的接口来补偿:

    public interface ICalculator<T>

    {

        T Add(T argument1, T argument2);

        T Subtract(T argument1, T argument2);

        T Divide(T argument1, T argument2);

        T Multiply(T argument1, T argument2);

    }

 

    public class Calculator : ICalculator<int>

    {

        public int Add(int argument1, int argument2)

        {

            return argument1 + argument2;

        }

        //Rest of the methods

}

五、接口级约束

一个接口可以定义它使用的泛型类型的约束where关键字)。例如:

public interface IList<T> where T : IComparable<T>

{...}

这样就得记住在接口范围内定义的约束的实现(IComparable<T>)。但是,一个接口不应当包含任何实现细节,而这样恰恰就违法了分离接口和实现的原则。对类型参数的约束,就会使接口与特定的实现操作耦合。

例如,约束接口上的类型参数来源于一个具体的类,就不是个好做法:

    public class Customer

    {...}

    public interface IList<T> where T:Customer

    {...}

这样做,实际上使泛型接口IList<T>只能用来管理Customers列表。如果要在接口级使用强类型实现多态性,应当定义一个新接口来专门管理Customer,以代替对泛型接口IList<T>多用途定义的曲解:

public interface ICustomerList:IList<Customer>

{...}

像下面这样约束一个默认构造器,也是应当避免的:

public interface IList<T> where T:new()

{...}

不是所有类型都有默认公共构造器(例如单件模式),并且接口不会真正关心它们没有构造器(接口是服务实现的契约);接口不能包含任何构造器的实现代码。

即使约束一个泛型接口的类型参数来源于另一个接口,也要十分谨慎地使用。例如,如果想要增加一个方法用来从List中移除一个特定item,就可能会对IList<T>增加一个IComparable<T>约束:

    public interface IList<T> where T:IComparable<T>

    {

        void Remove(T item);

        //Rest of the interface

}

当实现该方法时会常常包含对Listitem的比较操作,反之就表明类型参数需要支持IComparable<T>接口,这仍旧是一个“实现细节”。或许有其他方式来实现对类型参数的比较,或许根本没有实现。但任何情况都是与纯粹的接口定义毫不相干的。让类实现带有约束的泛型接口,保持接口自身的约束自由:

    public class List<T> : IList<T> where T : IComparable<T>

    {

        public void Remove(T item)

        {...}

        //Rest of the implementation

}

 

蓝色文字原文,请朋友们帮忙指正翻译一下:

If you want this level of strong typing with polymorphism,define a new interface dedicated to managing customersinstead of skewing the general-purpose difinition of the generic IList<T>

 

接口与泛型部分仍有部分残余,下次终结它。。。

 

根据原版英文翻译总结的,所以不足和错误之处请大家不吝指正,谢谢:)