泛型

33 篇文章 0 订阅

泛型定义:      

    通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。主要用于解决一系列类似的问题。这种机制允许将类名作为参数传递给泛型类型,并生成相应的对象。将泛型(包括类、接口、方法、委托等)看作模板可能更好理解,模板中的变体部分将被作为参数传进来的类名称所代替,从而得到一个新的类型定义。

优点:

通过允许指定泛型类或方法操作的特定类型,泛型功能将类型安全的任务从您转移给了编译器。不需要编写代码来检测数据类型是否正确,因为会在编译时强制使用正确的数据类型。减少了类型强制转换的需要和运行时错误的可能性。

一、和object实现的类有截然不同的区别:
    1.他是类型安全的。实例化了int类型的栈,就不能处理string类型的数据,其他数据类型也一样。
    2.无需装箱和折箱。这个类在实例化时,按照所传入的数据类型生成本地代码,本地代码数据类型已确定,所以无需装箱和折箱。
    3.无需类型转换。

二、泛型委托启用类型安全回调而无需创建多个委托类。例如,Predicate 泛型委托允许创建对特定类型实现您自己的搜索条件的方法,并允许将您的方法与 Array 类型的方法(如 Find、FindLast 和 FindAll)一起使用。

三、在很多情况下,Visual Basic、Visual C++ 和 C# 编译器能够从上下文中确定泛型方法调用使用的类型,极大地简化了使用泛型方法的语法。例如,下面的代码演示调用 BinarySearch 泛型方法以搜索字符串数组的短格式和长格式。在短格式中,编译器从方法变量的类型中推导出正确的类型参数。

 
 
int index = Array.BinarySearch(myArray, " test string "); int index = Array.BinarySearch< string>(myArray, " test string ");
实例:   

public class Stack<T>
    { private T[] m_item;
        public T Pop(){...}
        public void Push(T item){...}
        public Stack(int i)
        {
           this.m_item = new T[i];
        }
}

只是引入了通用数据类型T就可以适用于任何数据类型,并且类型安全的。这个类的调用方法:
//实例化只能保存int类型的类
Stack<int> a = new Stack<int>(100);
      a.Push(10);
      a.Push("8888"); //这一行编译不通过,因为类a只接收int类型的数据
      int x = a.Pop();

//实例化只能保存string类型的类
Stack<string> b = new Stack<string>(100);
b.Push(10);    //这一行编译不通过,因为类b只接收string类型的数据
b.Push("8888");
string y = b.Pop();

泛型类中数据类型的约束:

1、所有的派生约束必须放在类的实际派生列表之后 
如:public class LinkedList <K,T> :IEnumerable <T> where K:IComparable <K> 
{...} 
2、一个泛型参数上可以约束多个接口(用逗号分隔) 
public class LinkedList <K,T> where K:IComparable <K> ,IConvertible 
3、在一个约束中最多只能使用一个基类 
4、约束的基类不能是密封类或静态类 
5、不能将System.Delegate或System.Array约束为基类 
6、可以同时约束一个基类以及一个或多个接口,但是该基类必须首先出现在派生约束列表中。 
7、C#允许你将另一个泛型参数指定为约束 
public class MyClass <T,U> where T:U 
{...} 
8、可以自己定义基类或接口进行泛型约束 
9、自定义的接口或基类必须与泛型具有一致的可见性 

(2)、构造函数约束 
如: 
class Node <K,T> where T:new() 


注意: 
1、可以将构造函数的约束和派生约束结合起来,前提是构造函数的约束出现在约束列表中的最后 

(3)、引用/值类型约束 
1、可以使用struct约束将泛型参数约束为值类型(如int、bool、enum),或任何自定义结构 
2、同样可以使用class约束将泛型参数约束为引用类型 
3、不能将引用/值类型约束与基类约束一起使用,因为基类约束涉及到类 
4、不能使用结构和默认构造函数约束,因为默认构造函数约束也涉及到类 
5、虽然您可以使用类和默认构造函数约束,但是这样做没有任何价值 
6、可以将引用/值类型约束与接口约束组合起来,前提是引用/值类型约束出现在约束列表的开头 

   public ActionResult MapIndex()
        {
            
            Book[] bookArray = new Book[2];
            Book book1 = new Book(124, ".Net之美");
            Book book2 = new Book(45, "C# 3.0揭秘");
            bookArray[0] = book1;
            bookArray[1] = book2;
            SortHelper<Book> sorter = new SortHelper<Book>();
            sorter.BubbleSort(bookArray);
            foreach (Book b in bookArray)
            {
                Console.WriteLine("Id:{0}", b.Id);
                Console.WriteLine("Title:{0}\n", b.Title);
            }
            return View();
        }


        public class Book : IComparable
        {
            private int id;
            private string title;
            public Book() { }
            public Book(int id, string title) //构造
            {
                this.id = id;
                this.title = title;
            }
            public int Id
            {
                get { return id; }
                set { id = value; }
            }
            public string Title
            {
                get { return title; }
                set { title = value; }
            }
            // CODE:实现IComparable  CompareTo接口
            public int CompareTo(object obj)
            {
                Book book2 = (Book)obj;
                return this.Id.CompareTo(book2.Id);
            }
        }
        public class SortHelper<T> where T : IComparable  //约束T必须是IComparable 或 继承IComparable  
        {
            public void BubbleSort(T[] array)
            {
                int length = array.Length;


                for (int i = 0; i <= length - 2; i++)
                {
                    for (int j = length - 1; j >= 1; j--)
                    {


                        // 对两个元素进行交换
                        if (array[j].CompareTo(array[j - 1]) < 0)
                        {
                            T temp = array[j];
                            array[j] = array[j - 1];
                            array[j - 1] = temp;
                        }
                    }
                }
            }
        }
泛型类继承中:

1、泛型类继承中, 父类的类型参数已被实例化这种情况下子类不一定必须是泛型类
2、 父类的类型参数没有被实例化,但来源于子类,也就是说父类和子类都是泛型类,并且二者有相同的类型参数
//如果这样写的话,显然会报找不到类型T,S的错误  
public class TestChild : Test< T, S> { }  
//正确的写法应该是  
public class TestChild : Test< string, int>{ }  
public class TestChild< T, S> : Test< T, S> { }  
public class TestChild< T, S> : Test< String, int> { } 

泛型接口:

泛型接口的类型参数要么已实例化,要么来源于实现类声明的类型参数

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 泛型
{
    class 泛型接口
    {
        public static void Main()
        {
            PersonManager man = new PersonManager();
            Person per = new Person();
            man.PrintYourName(per);
            Person p1 = new Person();
            p1.Name = "p1";
            Person p2 = new Person();
            p2.Name = "p2";
            man.SwapPerson<Person>(ref p1, ref p2);
            Console.WriteLine( "P1 is {0} , P2 is {1}" , p1.Name ,p2.Name);
            Console.ReadLine();
        }
    }
 
  //泛型接口
    interface IPerson<T>
    {
        void PrintYourName( T t);
    }

    class Person
    {
        public string Name = "aladdin";
    }

    class PersonManager : IPerson<Person>
    {
        #region IPerson<Person> 成员
        public void PrintYourName( Person t )//实现接口
        {
            Console.WriteLine( "My Name Is {0}!" , t.Name );
        }

        #endregion
        //交换
        public void SwapPerson<T>( ref  T p1 , ref T p2)
        {
            T temp = default(T) ;
            temp = p1;
            p1 = p2;
            p2 = temp;
        }
    }
}

接口、抽象类继承#region 接口、抽象类继承   
 64    public interface ISomeInterface6<T>   
 65    {   
 66        T SomeMethod(T t);   
 67    }   
 68    public abstract class BaseClass6<T>   
 69    {   
 70        public abstract T SomeMethod(T t);   
 71    }   
 72    public class SubClass6<T> : BaseClass6<T>,ISomeInterface6<T>   
 73    {   
 74        public override T SomeMethod(T t)   
 75        { return default(T); }   
 76    }   
 77    #endregion  
 
 
泛型委托: 

using System;   
 2using System.Collections.Generic;   
 3using System.Text;   
 4   
 5namespace VS2005Demo2   
 6{   
 7    泛型委托#region 泛型委托   
 8    public class MyClass40<T>   
 9    {   
10        public delegate void GenericDelegate(T t);   
11        public void SomeMethod(T t)   
12        { }   
13    }   
15    public class MyClassTest40   
16    {   
17        public void Tests()   
18        {   
19            MyClass40<int> obj = new MyClass40<int>();   
20            MyClass40<int>.GenericDelegate del;   
21   
22            del = new MyClass40<int>.GenericDelegate(obj.SomeMethod);   
23            del(3);   
24   
25            //委托推理   
26            del = obj.SomeMethod;   
27   
28        }   
29    }   
30    #endregion   
31   
32    委托泛型参数#region 委托泛型参数   
33    public class MyClass41<T>   
34    {   
35        public delegate void GenericDelegate<X>(T t, X x);   
36    }   
37   
38    //外部委托   
39    public delegate void GenericDelegate<T>(T t);   
40   
41    public class MyClass42   
42    {   
43        public void SomeMethod(int number)   
44        { }   
45    }   
46   
47    public class MyClassTest42   
48    {   
49        public void Test()   
50        {   
51            MyClass42 obj = new MyClass42();   
52            GenericDelegate<int> del;   
53            //del = new GenericDelegate<int>(obj.SomeMethod);   
54   
55            del = obj.SomeMethod;   
56            del(3);   
58        }   
59    }  
 
61    #endregion   
63    委托泛型参数#region 委托泛型参数   
64    public delegate void MyDelegate<T>(T t) where T : IComparable<T>;   
65    #endregion   
67    事件#region 事件   
69    public delegate void GenericEventHandler<S, A>(S sender, A args);   
70       
71    public class MyPublisher   
72    {   
73        public event GenericEventHandler<MyPublisher, EventArgs> MyEvent;   
74        public void FireEvent()   
75        {   
76            MyEvent(this, EventArgs.Empty);   
77        }   
78    }   
80    public class MySubscriber<A> //Optional: can be a specific type   
81    {   
82        public void SomeMethod(MyPublisher sender, A args)   
83        { }   
84    }   
85    public class MyClassTest43   
86    {   
87        public void Test()   
88        {   
89            MyPublisher publisher = new MyPublisher();   
90            MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();   
91            publisher.MyEvent += subscriber.SomeMethod;   
92        }   
93    }   
94    #endregion   
95} 








         

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值