step1-泛型2

发布时间:2016-12-9 0:22:54 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"step1-泛型2",主要涉及到step1-泛型2方面的内容,对于step1-泛型2感兴趣的同学可以参考一下。

一泛型优点       泛型类和泛型方法同时具备可重用性、类型安全和效率,这是非泛型类和非泛型方法无法具备的。以下依次对其进行详细说明。 1.类型安全 非泛型,如当ArrayList添加了一个字符类型时,存在一个字符向对象的隐式转换。同样,如果自列表检索一个字符类型对象时,存在一个自Object向字符类型的显示转换。 而检索类型对象时,是在运行时进行检查,因此,存在不安全性(如eg2非泛型,在运行时,将"e"转换为int时,会抛出类型转换的错误)。 相反,泛型如List<String> 允许程序在编译时而不是运行时对变量类型进行确定及检查(如eg1泛型). 2.效率 (1) 在JIT编译时而不是在执行过程中进行类型检查,性能会得到提高。 (2) 另外,对于值类型而言,使用非泛型需要对值类型进行装箱,拆箱,会浪费很多时间。 eg1泛型: List<String>  lis=new List<string>(); lis.Add("a");//不进行装箱。 lis.Add(System.DateTime);//在编译时便会报错,而不是在运行时才检查错误。 string a=lis[0];//不需要类型转换。 eg2非泛型:        public ArrayList AddToArrayList()         {             ArrayList arrlist =new ArrayList();             arrlist.Add(1);//装箱string-->object             arrlist.Add(2);             arrlist.Add("e");             return arrlist;         }         public void ReadFromArrayList(ArrayList arr)         {             int[] intvalue = new int[3];             for(int i=0; i<arr.Count; i++)             {                 intvalue[i] = Convert.ToInt32(arr[i]);             }         } 3.可重用性 泛型能够实现对具有相同功能的代码重用。避免了重写代码带来的烦恼。 3.1需求描述 public classDog {    public string Name { get; set; } }   public classCat { public string Name {get; set; } }     现在有一个需求,要求将Dog和Cat的名字打印出来,写两个方法,分别用于打印Dog和Cat的名字: public staticvoid PrintDogName(Dog dog) {  Console.WriteLine(dog.Name); } public staticvoid PrintCatName(Cat cat) {  Console.WriteLine(cat.Name); }   3.2合并方法 public staticvoid PrintName<T>(T t) { if (t is Dog) { Console.WriteLine((t as Dog).Name); return; } if (t is Cat) { Console.WriteLine((t as Cat).Name); return; } } 3.3最终优化 而(2)中方法是把方法合并成一个了,但总的代码量没有减少。只是把原来两个方法里的代码拿到一个方法里来,可以将Dog类和Cat类抽象出一个接口: interface IName { string Name { get; set; } }    public class Dog : IName { public string Name {get; set; } } public class Cat:IName { public string Name {get; set; } } //限制泛型:必须实现Iname接口。 public staticvoid PrintName<T>(T t)where T:IName { Console.WriteLine(t.Name); }   二泛型应用 泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符可以具有一个或多个类型。 1泛型类 1.1简单泛型类定义 带有泛型参数列表。 public class Generic<T> {       public T Field; } 1.2 如何实例化泛型类 需指定实际类型来替换类型参数。这会建立一个新的泛型类,称为构造泛型类,选定的类型将替换所有出现的类型参数。 Generic<string> g = new Generic<string>(); g.Field = "A string"; 2 泛型方法 2.1泛型方法定义 具有两个参数列表的方法:一个泛型类型参数列表和一个形参列表。类型参数可以作为返回类型或形参的类型出现。 2.2泛型方法解析 示例中泛型类型参数列表为<T>,形参列表为(T arg)。形参和返回类型都为泛型类型T。 T Generic<T>(T arg) { T temp = arg; ...} 2.3注意 只有当方法具有它自己的类型参数列表时,才能称其为泛型方法。在下面的代码中,只有方法 G是泛型方法。 class A  {       T G<T>(T arg) {...} } class Generic<T> {  T M(T arg) {...} } 3 泛型接口 3.1泛型接口定义       以常用泛型接口为例:System. IComparable<T>和 System. IEquatable< T> 。IComparable< T>接口定义 CompareTo 方法,该方法确定实现类型的实例的排序顺序。 IEquatable<T>接口定义Equals 方法,该方法确定实现类型的实例的相等性。示例中泛型类型参数列表为<T>。    public interfaceIEquatable<T>     {         bool Equals(T other); } 3.2泛型接口使用 public classPerson : IEquatable<Person> {       public Person(string lastName,string ssn)     {         this.SSN = ssn;         this.LastName = lastName;     }     public string SSN     {         get { return this.uniqueSsn; }         set         {             uniqueSsn = value;         }     }       public string LastName     {         get { return this.lName; }         set         {             lName = value;         }     }       public bool Equals(Person other) //继承接口的方法。     {         if (this.uniqueSsn == other.SSN)             return true;         else             return false;     }  } public classTestIEquatable {     public static void Main()     {         // Create a Person object for each job applicant.         Person applicant1 = new Person("Jone","1");         Person applicant2 = new Person("Jone","2");         applicants.Add(applicant1);         applicants.Add(applicant2);         // Create a Person object for the final candidate.         Person candidate = new Person("Jone","2");         Console.WriteLine("{0}({1}) already on file: {2}.",                   applicant2.LastName,                   applicant2.SSN,                   applicant2.Equals(applicant1));     } }   三泛型重点之泛型约束 1 泛型约束的概述 泛型约束的作用:对于所定义的泛型类,在客户端代码,可以对其实例化泛型类时所用的类型参数的类型种类施加限制。若在客户端代码中,尝试使用某个约束所不允许的类型来实例化类,则会产生编译错误。 约束的类型有以下六种: 约束 说明 T:结构 类型参数必须是值类型。可以指定除Nullable 以外的任何值类型。 T:类 类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。 T:new() 类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。 T:<基类名> 类型参数必须是指定的基类或派生自指定的基类。 T:<接口名称> 类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。 T:U 为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。   2.泛型约束的演练 2.1代码模板:     class MyList<T> where T:new ()     {         List<T> list = new List<T>();         public T this[int i]         {             get { return list[i]; }             set { this.list[i] = value; }         }     }       class Person     {         public string Name { get; set; }     } 2.2指定泛型参数为值类型 (1)根据2.1代码模板,指定泛型类型为值类型。 class MyList<T> where T:struct { }  (2) 在客户端实例化泛型类型: MyList<Person> list = new MyList<Person>(); 出现编译错误,提示: 类型“GencConstraint.Person”必须是不可为 null 的值类型才能用作泛型类型或方法“GencConstraint.MyList<T>”中的参数“T”。 (3) 在客户端使用如下方式的实例化,将一切正常: MyList<int> list = new MyList<int>(); 2.3指定泛型参数为引用类型 (1)根据2.1代码模板,指定泛型类型为引用类型。 class MyList<T> where T:class { } (2)在客户端使用如下方式的实例化,将一切正常: MyList<Person> list = new MyList<Person>(); (3)在客户端使用如下方式的实例化,出现编译错误: MyList<int> list = new MyList<int>(); 2.4指定泛型参数为无参的公共的构造函数 (1)根据2.1代码模板,指定泛型类型如下: class MyList<T> where T:new() { } (2)为Person类指定私有构造函数: class Person {          public string Name { get; set; }          private Person()          {              //do nothing          } }  出现编译错误,提示: “GencConstraint.Person”必须是具有公共的无参数构造函数的非抽象类型,才能用作泛型类型或方法“GencConstraint.MyList<T>”中的参数“T”。 2.5指定泛型参数必须派生于指定基类 (1)新增基类:     abstract class SeniorAnimal//高级动物     {         public abstract void Speak();//会说话     }  (2)根据2.1代码模板,指定泛型参数必须派生于基类SeniorAnimal: class MyList<T> where T: SeniorAnimal { } (3) 在客户端实例化泛型类型: MyList<Person> list = new MyList<Person>(); 出现编译错误,提示: 不能将类型“GencConstraint.Person”用作泛型类型或方法“GencConstraint.MyList<T>”中的类型参数“T”。没有从“'GencConstraint.Person”到“GencConstraint.SeniorAnimal”的隐式引用转换。 (4)修改代码,使Person类继承自SeniorAnimal类:     class Person : SeniorAnimal     {         public string Name { get; set; }           public override void Speak()         {             Console.WriteLine("我会说英语!");         }     } 则编译成功。 2.6指定泛型参数必须实现指定接口。 示例同2.4,不再讲述。 2.7指定泛型参数必须派生于泛型类型U(裸类型约束) 格式如下: class MyList<U> where U : SeniorAnimal {         List<U> list = new List<U>();          public void ShowInfo<T>() where T : U          {          } }  

上一篇:黑马程序员_java_IO流
下一篇:C# Ini文件操作实例

相关文章

关键词: step1-泛型2

相关评论