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

六、泛型派生约束

当一个泛型类强制它的一个泛型参数来源于一个接口时,客户端可以为这个类型参数提供一个该接口的具体实现:

    public class ListClient<L, T> where L : IList<T>

    {

        public void ProcessList(L list)

        {...}

    }

 

    public class NumberList : IList<int>

{...}

 

    ListClient<NumberList,int> client=new ListClient<NumberList,int>();

    NumberList numbers=new NumberList();

 client.ProcessList(numbers);

但是,可以同样通过指定一个接口类型参数来满足约束,而不是它的一个具体实现:

    public class List<T>:IList<T>

{...}

    ListClient<IList<int>,int> client=new ListClient<IList<int>,int>();

    IList<int> numbers = new List<int>();

 client.ProcessList(numbers);

或者可以这样替代:

    public class AnotherClient<U>

    {

        ListClient<IList<U>,U> m_listClient;

}

这样有助于把客户端代码从具体实现中分离出来。

 

七、泛型,接口和转换

C#编译器只允许把泛型类型参数隐式转换为object,或者是约束规定的类型,这都是类型安全的:

    public interface ISomeInterface

    {...}

 

    public class BaseClass

    {...}

    public class MyClass<T> where T:BaseClass,ISomeInterface

    {

        void SomeMethod(T t)

        {

            ISomeInterface obj1 = t;

            BaseClass obj2 = t;

            object obj3 = t;

        }

}

编译器允许把泛型类型参数显式转换为其他接口,而不可以是类:

    public class MyClass<T>

    {

        void SomeMethod(T t)

        {

            ISomeInterface obj = (ISomeInterface)t; //通过编译

            BaseClass obj2 = (BaseClass)t;          //不会通过编译

        }

}

显式转换是危险的,因为它可能会在运行过程中显式转换失败时抛出异常。一个更好的方法就是使用isas操作符(可参阅:《Programming .Net Components》学习笔记(二)),这里再记一下is的用法:

    public interface IMyInterface

    {...}

    public interface ISomeInterface<T>

    {...}

    public class MyClass<T>

    {

        public void MyMothod(T t)

        {

            if (t is IMyInterface)

            {...}

            if (t is ISomeInterface<T>)

            {...}

        }

}


八、泛型接口方法

C# 2.0接口方法也可以定义泛型类型参数,用来指定具体的执行范围:

    public interface IMyInterface<T>

    {

        void MyMethod<X>(T t, X x);

}

这是一个十分重要的功能,它允许可以随时用不同的类型来调用方法,对于多用途类来说是十分方便的。即使是非泛型接口也可以定义泛型方法,这是方法独有的能力。属性和索引器只能在接口定义。当调用一个定义了泛型类型参数的接口方法时,就可以在调用点上提供特定类型:

    public interface IMyInterface

    {

        void MyMethod<X>(T t, X x);

    }

 

    public class MyClass : IMyInterface

    {

        public void MyMehod<T>(T t)

        {...}

}

IMyInterface obj = new MyClass();

obj.MyMethod<int>(3);

另外,当方法被请求时,C#编译器可以根据传入的参数类型足够智能地推理得到正确的类型,所以可以不指定特定的类型:

IMyInterface obj = new MyClass();

obj.MyMethod(3);

这种功能被称作“generic type inference(泛型类型推理)”。需要注意的是编译器不能单独基于返回值的类型来推理:

    public interface IMyInterface

    {

        T MyMethod<T>();

    }

    public class MyClass : IMyInterface

    {

        public T MyMethod<T>()

        {...}

    }

IMyInterface obj = new MyClass();

 int number = obj.MyMethod();      //不会通过编译

当一个接口方法定义自己独有的泛型类型参数时,也可以定义类型约束。但是,建议最好不要把在接口级的约束扩展到方法级的范例类型参数。

 

泛型与接口部分结束,泛型可以使接口更加灵活的应用,小心设置约束,不要时接口依赖于具体的实现或者是类型,注意类型安全。

 

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

However,you can also satisfy the constraint by specifying as a type parameter the very interface the type parameter is constrained against,not a particular implementation of it

 

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

你可能感兴趣的:(programming)