好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C# 之泛型详解

   

 

泛型中的静态成员变量
在C#1.x中,我们知道类的静态成员变量在不同的类实例间是共享的,并且他是通过类名访问的。C#2.0中由于引进了泛型,导致静态成员变量的机制出现了一些变化:静态成员变量在相同封闭类间共享,不同的封闭类间不共享。

这也非常容易理解,因为不同的封闭类虽然有相同的类名称,但由于分别传入了不同的数据类型,他们是完全不同的类,比如:

Stack<int> a = new Stack<int>();

Stack<int> b = new Stack<int>();

Stack<long> c = new Stack<long>();

类实例a和b是同一类型,他们之间共享静态成员变量,但类实例c却是和a、b完全不同的类型,所以不能和a、b共享静态成员变量。

泛型中的静态构造函数
静态构造函数的规则:只能有一个,且不能有参数,他只能被.NET运行时自动调用,而不能人工调用。

泛型中的静态构造函数的原理和非泛型类是一样的,只需把泛型中的不同的封闭类理解为不同的类即可。以下两种情况可激发静态的构造函数:

1.       特定的封闭类第一次被实例化。

2.       特定封闭类中任一静态成员变量被调用。

 

泛型类中的方法重载
方法的重载在.Net Framework中被大量应用,他要求重载具有不同的签名。在泛型类中,由于通用类型T在类编写时并不确定,所以在重载时有些注意事项,这些事项我们通过以下的例子说明:

public class Node<T, V>

    {

        public T add(T a, V b)          //第一个add

        {

            return a;

        }

        public T add(V a, T b)          //第二个add

        {

            return b;

        }

        public int add(int a, int b)    //第三个add

        {

            return a + b;

        }

}

上面的类很明显,如果T和V都传入int的话,三个add方法将具有同样的签名,但这个类仍然能通过编译,是否会引起调用混淆将在这个类实例化和调用add方法时判断。请看下面调用代码:

Node<int, int> node = new Node<int, int>();

    object x = node.add(2, 11);

这个Node的实例化引起了三个add具有同样的签名,但却能调用成功,因为他优先匹配了第三个add。但如果删除了第三个add,上面的调用代码则无法编译通过,提示方法产生的混淆,因为运行时无法在第一个add和第二个add之间选择。

Node<string, int> node = new Node<string, int>();

        object x = node.add(2, "11");

   这两行调用代码可正确编译,因为传入的string和int,使三个add具有不同的签名,当然能找到唯一匹配的add方法。

由以上示例可知,C#的泛型是在实例的方法被调用时检查重载是否产生混淆,而不是在泛型类本身编译时检查。同时还得出一个重要原则:

当一般方法与泛型方法具有相同的签名时,会覆盖泛型方法。

 

泛型类的方法重写
方法重写(override)的主要问题是方法签名的识别规则,在这一点上他与方法重载一样,请参考泛型类的方法重载。

 

泛型的使用范围
本文主要是在类中讲述泛型,实际上,泛型还可以用在类方法、接口、结构(struct)、委托等上面使用,使用方法大致相同,就不再讲述。

小结
C# 泛型是开发工具库中的一个无价之宝。它们可以提高性能、类型安全和质量,减少重复性的编程任务,简化总体编程模型,而这一切都是通过优雅的、可读性强的语法完成的。尽管 C# 泛型的根基是 C++ 模板,但 C# 通过提供编译时安全和支持将泛型提高到了一个新水平。C# 利用了两阶段编译、元数据以及诸如约束和一般方法之类的创新性的概念。毫无疑问,C# 的将来版本将继续发展泛型,以便添加新的功能,并且将泛型扩展到诸如数据访问或本地化之类的其他 .NET Framework 领域。

泛型中分为开放类型和封闭类型,具体区分如下:
开放类型:具有类型参数的类型就是开放类型(所有未绑定泛型类型都属于开放类型)
封闭类型:为每个类型参数都传递了实际的数据类型(类型实参)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 声明开放泛型类型
        public sealed class DictionaryStringKey<T> : Dictionary<string, T>
     {
  
     }
  
static void Main(string[] args)
        {
            object o = null;
            // Dictionary<,>是一个开放类型,它有2个类型参数
            Type t = typeof(Dictionary<,>);
            // 创建开放类型的实例(创建失败,出现异常)
            o = CreateInstance(t);
            Console.WriteLine();
            // DictionaryStringKey<>也是一个开放类型,但它有1个类型参数
            t = typeof(DictionaryStringKey<>);
            // 创建该类型的实例(同样会失败,出现异常)
            o = CreateInstance(t);
            Console.WriteLine();
            // DictionaryStringKey<int>是一个封闭类型
            t = typeof(DictionaryStringKey<int>);
            // 创建封闭类型的一个实例(成功)
            o = CreateInstance(t);
            Console.WriteLine("对象类型 = " + o.GetType());
            Console.Read();
        }
 
       // 创建类型
        private static object CreateInstance(Type t)
        {
            object o = null;
            try
            {
                // 使用指定类型t的默认构造函数来创建该类型的实例
                o = Activator.CreateInstance(t);
                Console.WriteLine("已创建{0}的实例", t.ToString());
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return o;
        }



由于开放类型并没有指定具体的初始化类型,所以不能创建该类型的一个实例

原文:https://www.cnblogs.com/yueyue184/p/5032156.html

查看更多关于C# 之泛型详解的详细内容...

  阅读:8315次