泛型掌握

//************************


        第一部分 泛型类


//************************

//对于泛型类 Node<T>,,客户端代码可以通过指定类型参数引用该类,以创建封闭式构造类型 //(Node<int>),或者可以让类型参数处于未指定状态(例如在指定泛型基类时)以创建开放式构造类型 //(Node<T>)。泛型类可以从具体的、封闭式构造或开放式构造基类继承:

//BaseNodeGeneric<int> --封闭式构造
//BaseNodeGeneric<T>  --开放式构造


class BaseNode { }
class BaseNodeGeneric<T> { }

// concrete type
class NodeConcrete<T> : BaseNode { }

//closed constructed type --封闭式构造
class NodeClosed<T> : BaseNodeGeneric<int> { }

//open constructed type --开放式构造
class NodeOpen<T> : BaseNodeGeneric<T> { }
===============================================================================================================

//非泛型(具体)类可以从封闭式构造基类继承,但无法从开放式构造类或裸类型参数继承,因为在运行时客户端代码无法提供实例化基//类所需的类型变量。


//No error
class Node1 : BaseNodeGeneric<int> { }

//Generates an error
//class Node2 : BaseNodeGeneric<T> {}

//Generates an error
//class Node3 : T {}
================================================================================================================
//从开放式构造类型继承的泛型类必须为任何未被继承类共享的基类类型参数提供类型变量,如以下代码所示:

C# 复制代码
class BaseNodeMultiple<T, U> { }

//No error
class Node4<T> : BaseNodeMultiple<T, int> { }

//No error
class Node5<T, U> : BaseNodeMultiple<T, U> { }

//Generates an error
//class Node6<T> : BaseNodeMultiple<T, U> {}

================================================================================================================
从开放式构造类型继承的泛型类必须为任何未被继承类共享的基类类型参数提供类型变量,如以下代码所示:

C# 复制代码
class BaseNodeMultiple<T, U> { }

//No error
class Node4<T> : BaseNodeMultiple<T, int> { }

//No error
class Node5<T, U> : BaseNodeMultiple<T, U> { }

//Generates an error
//class Node6<T> : BaseNodeMultiple<T, U> {}

================================================================================================================
//******没明白 超集?
从开放式构造类型继承的泛型类必须指定约束,这些约束是基类型约束的超集或暗示基类型约束:

//NodeItem<T>  是一个基类型

class NodeItem<T> where T : System.IComparable<T>, new() { }
class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { }

================================================================================================================
泛型类型可以使用多个类型参数和约束,如下所示:

C# 复制代码
class SuperKeyType<K, V, U>
    where U : System.IComparable<U>
    where V : new()
{ }
================================================================================================================

开放式构造类型和封闭式构造类型可以用作方法参数:

开放式构造类型
void Swap<T>(List<T> list1, List<T> list2)
{
    //code to swap items
}
封闭式构造类型
void Swap(List<int> list1, List<int> list2)
{
    //code to swap items
}

泛型类是不变的。也就是说,如果输入参数指定 List<BaseClass>,则当您试图提供 List<DerivedClass> 时,将会发生编译时错误。
================================================================================================================


//************************


        第二部分 泛型接口


//************************

================================================================================================================
一个接口可定义多个类型参数,如下所示:

C# 复制代码
interface IDictionary<K, V>
{
}

类之间的继承规则同样适用于接口:

C# 复制代码
interface IMonth<T> { }

interface IJanuary     : IMonth<int> { }  //No error
interface IFebruary<T> : IMonth<int> { }  //No error
interface IMarch<T>    : IMonth<T> { }    //No error
//interface IApril<T>  : IMonth<T, U> {}  //Error

================================================================================================================

如果泛型接口为逆变的,即仅使用其类型参数作为返回值,则此泛型接口可以从非泛型接口继承。在 .NET Framework 类库中,IEnumerable<T> 从 IEnumerable 继承,因为 IEnumerable<T> 仅在 GetEnumerator 的返回值和当前属性 getter 中使用 T。

具体类可以实现已关闭的构造接口,如下所示:

C# 复制代码
interface IBaseInterface<T> { }

class SampleClass : IBaseInterface<string> { }

================================================================================================================

只要类参数列表提供了接口必需的所有参数,泛型类便可以实现泛型接口或已关闭的构造接口,如下所示:

C# 复制代码
interface IBaseInterface1<T> { }
interface IBaseInterface2<T, U> { }

class SampleClass1<T> : IBaseInterface1<T> { }          //No error
class SampleClass2<T> : IBaseInterface2<T, string> { }  //No error

================================================================================================================
//************************


        第二部分 泛型方法


//************************

================================================================================================================

泛型方法是使用类型参数声明的方法,如下所示:

C# 复制代码
static void Swap<T>(ref T lhs, ref T rhs)
{
    T temp;
    temp = lhs;
    lhs = rhs;
    rhs = temp;
}

================================================================================================================

下面的代码示例演示一种使用 int 作为类型参数的方法调用方式:

C# 复制代码
public static void TestSwap()
{
    int a = 1;
    int b = 2;

    Swap<int>(ref a, ref b);
    System.Console.WriteLine(a + " " + b);
}

也可以省略类型参数,编译器将推断出该参数。下面对 Swap 的调用等效于前面的调用:

///***
Swap(ref a, ref b);

================================================================================================================

在泛型类中,非泛型方法可以访问类级别类型参数,如下所示:

class SampleClass<T>
{
void Swap(ref T lhs, ref T rhs) { }
}

如果定义的泛型方法接受与包含类相同的类型参数,编译器将生成警告 CS0693,因为在方法范围内,为内部 T 提供的参数将隐藏为外部 T 提供的参数。除了类初始化时提供的类型参数之外,如果需要灵活调用具有类型参数的泛型类方法,请考虑为方法的类型参数提供其他标识符,如下面示例中的 GenericList2<T> 所示。

class GenericList<T>
{
    // CS0693
    void SampleMethod<T>() { }
}

class GenericList2<T>
{
    //No warning
    void SampleMethod<U>() { }
}

================================================================================================================

使用约束对方法中的类型参数启用更专门的操作。此版本的 Swap<T> 现在称为 SwapIfGreater<T>,它只能与实现 IComparable<T> 的类型参数一起使用。

void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
    T temp;
    if (lhs.CompareTo(rhs) > 0)
    {
        temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}

泛型方法可以使用许多类型参数进行重载。例如,下列方法可以全部存在于同一个类中:

void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }

posted on 2007-10-24 16:31  willlove  阅读(75)  评论(0)    收藏  举报

导航