泛型是C#和.Net的一个重要概念,泛型不只是C#编程语言中的一部分,并且与程序集中的IL(Intermediate Language)代码紧密的集成。html
在平时编程过程当中,经常会出现编写一些差很少的代码块,不一样的仅是处理不一样的数据类型。好比一个处理int数据的方法,如今新加了string类型的数据。是否是把以前的方法复制一遍,而后修改类型int为string。固然这样的方法是没有错的,那么后面又新增了其余的许多类型怎么办?仍是复制修改吗?这样代码看上去很冗余,很复杂。这时候泛型就出现了。下面咱们看下为什么使用泛型吧。编程
下面介绍下泛型的优势,尤为是下面几个:c#
1、性能安全
泛型的一个主要优势就是性能,在泛型集合类和非泛型集合类中,对值类型使用非泛型集合类,在把值类型转换为引用类型和把引用类型转换为值类型的时候,须要进行装箱和拆箱的操做(前面的文章中讲到了拆箱和装箱会形成必定的性能损失),当集合数据量大的时候形成的性能损失也就随之的增大了。编程语言
使用非泛型集合时:ide
var list = new ArrayList(); list.Add(100);//装箱 int-object
int i = (int)list[0];//拆箱 object-int
foreach (int item in list) { Console.WriteLine(item);//遍历拆箱输出
}
使用泛型集合类时:函数
var list = new List<int>(); list.Add(100);//无装箱操做
int i = list[0];//无拆箱拆箱
foreach (int item in list) { Console.WriteLine(item);//无拆箱操做
}
减小装箱拆箱操做,节省了性能消耗。这也就是泛型的主要优势了。性能
2、类型安全学习
泛型另外一个优势就是类型安全,这里咱们仍是使用非泛型集合类ArrayList()和泛型集合类List<T>来作案例。spa
非泛型集合类ArrayList():
var list = new ArrayList(); list.Add(100);// 添加一个int类型
list.Add("string");//添加一个string类型
foreach (int item in list) { Console.WriteLine(item);//遍历循环输出
} 这里容许输出和抛出异常: System.InvalidCastException:“Unable to cast object of type 'System.String' to type 'System.Int32'.”
没法强制把”string”转换成int类型。
咱们再看泛型集合类:
var list = new List<int>(); list.Add(100);// 添加一个int类型 list.Add("string");//添加一个string类型,编译器报错,没法从string转换到int
foreach (int item in list) { Console.WriteLine(item);//遍历循环输出 }
在添加”string”类型的时候编译器报错,没法添加。这里也就杜绝了后续的错误。这也就是保证了类型的安全。
3、二进制代码重用
泛型容许更好的重用二进制代码,泛型类型能够定义一次,而且能够再许多不一样的类型实例化,相比C++来讲,不用每次访问源代码。
例如上面使用的泛型集合类,using System.Collections.Generic; 中的List<T>类,能够用int,string,自定义类去实例化。
泛型类型还能够在一种语言定义,而后再其余任何.Net语言中使用。
这里咱们能够来了解下建立泛型类了以后,泛型类有哪些功能呢?
1、默认值
在咱们定义了泛型类型以后如何赋值呢?
public class Tclass<T> { public static T Get() { T a = default; return a; } }
由于在泛型中初始给值很差给,你说给null吧,null是给引用类型的,你是给0吧,这又是给值类型的,这时候出现了default,当时引用类型调用时就给null,当时值类型时就0。
2、约束
说到泛型类型的约束时,不得不提关键字where,where是用来限制参数的范围的,若是不符合where条件指定的参数范围,编译是不容许经过的。
这里泛型类型的约束主要能够分为如下6中
public class Tclass<T,U>
where T:class //类型参数为引用类型
where U:struct //类型参数为值类型
{}
/// <summary>
/// 接口 /// </summary>
interface Itest { } /// <summary>
/// 定义一个字典类型 /// </summary>
/// <typeparam name="TK"></typeparam>
/// <typeparam name="TV"></typeparam>
class Dictionary<TK, TV>
where TK : IComparable, IEnumerable where TV : Itest { public void Add(TK key, TV val) { } }
class Ttest { } class Tclass<T> where T:Ttest { }
class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new() { // ... }
public class Tclass<T> where T:IComparable { }
3、继承
泛型类型的继承与普通类的继承类似但不一样。
/// <summary>
/// 抽象基类,泛型类型 /// </summary>
/// <typeparam name="T"></typeparam>
public abstract class Ttest<T> { public abstract T Add(T x, T y); } /// <summary>
/// 继承抽象基类,实现int类型 /// </summary>
/// <typeparam name="T"></typeparam>
class Tclass<T> : Ttest<int> { public override int Add(int x, int y) => x + y; }
4、静态成员
泛型类型的静态成员须要特殊的关注,泛型类的静态成员只能在类的一个实例中共享。
/// <summary>
/// 泛型类型,静态字段x /// </summary>
/// <typeparam name="T"></typeparam>
public class Ttest<T> { public static int x; } class Program { static void Main(string[] args) { Ttest<string>.x = 111; Ttest<int>.x = 222; Console.WriteLine(Ttest<string>.x); } }
上面事例中最后输出的为111,
这里咱们主要是介绍了泛型的优势及泛型类型的功能。在咱们平常的编程中会发现不少地方可使用泛型。提升代码的扩展性及重用性。同时也能够减小对object类型的使用,采用泛型类型的使用来替代。较少对性能的消耗。咱们下一节主要是对泛型类型的协变及抗变进行必定的理解。
只要认为是对的就去作,坚持去作,不要在意别人的见解,哪怕是错,至少你有去作过证实曾经你努力过。
欢迎你们扫描下方二维码,和我一块儿学习更多的C#知识