这篇文章主要介绍“C#泛型的用法及关键字作用”,在日常操作中,相信很多人在C#泛型的用法及关键字作用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#泛型的用法及关键字作用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个非常重要的新功能。
我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样。但我们没有办法,只能分别写多个方法来处理不同的数据类型。这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入不同种类型参数的办法呢?泛型的出现就是专门来解决这个问题的,可以看出,微软还是很贴心的。
接下来我们来看一段代码。
public class GenericClass { public void ShowInt(int n) { Console.WriteLine("ShowInt print {0},ShowInt Parament Type Is {1}",n,n.GetType()); } public void ShowDateTime(DateTime dt) { Console.WriteLine("ShowDateTime print {0},ShowDateTime Parament Type Is {1}", dt, dt.GetType()); } public void ShowPeople(People people) { Console.WriteLine("ShowPeople print {0},ShowPeople Parament Type Is {1}", people, people.GetType()); } }
static void Main(string[] args) { GenericClass generice = new GenericClass(); generice.ShowInt(11); generice.ShowDateTime(DateTime.Now); generice.ShowPeople(new People { Id = 11, Name = "Tom" }); Console.ReadKey(); }
显示结果:
我们可以看出这三个方法,除了传入的参数不同外,其里面实现的功能都是一样的。在1.1版的时候,还没有泛型这个概念,那么怎么办呢。就有人想到了OOP三大特性之一的继承,我们知道,C#语言中,object是所有类型的基类,将上面的代码进行以下优化:
public class GenericClass { public void ShowObj(object obj) { Console.WriteLine("ShowObj print {0},ShowObj Parament Type Is {1}", obj, obj.GetType()); } } static void Main(string[] args) { Console.WriteLine("*****************object调用*********************"); generice.ShowObj(11); generice.ShowObj(DateTime.Now); generice.ShowObj(new People { Id = 11, Name = "Tom" }); Console.ReadKey(); }
显示结果:
我们可以看出,目地是达到了。解决了代码的可读性,但是这样又有个不好的地方了,我们这样做实际上是一个装箱拆箱操作,会损耗性能。
终于,微软在2.0的时候发布了泛型。接下来我们用泛型方法来实现该功能。
在使用泛型方法之前,我们先来了解下有关于泛型的一些知识。
在泛型类型或方法定义中,类型参数是在其实例化泛型类型的一个变量时,客户端指定的特定类型的占位符。 泛型类(GenericList<T>
)无法按原样使用,因为它不是真正的类型;它更像是类型的蓝图。 若要使用GenericList<T>
,客户端代码必须通过指定尖括号内的类型参数来声明并实例化构造类型。 此特定类的类型参数可以是编译器可识别的任何类型。 可创建任意数量的构造类型实例,其中每个使用不同的类型参数,如下所示:
GenericList<float> list1 = new GenericList<float>(); GenericList<ExampleClass> list2 = new GenericList<ExampleClass>(); GenericList<ExampleStruct> list3 = new GenericList<ExampleStruct>();
在GenericList<T>
的每个实例中,类中出现的每个T
在运行时均会被替换为类型参数。 通过这种替换,我们已通过使用单个类定义创建了三个单独的类型安全的有效对象。
定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的几种类型施加限制。 如果客户端代码尝试使用约束所不允许的类型来实例化类,则会产生编译时错误。 这些限制称为约束。 通过使用where
上下文关键字指定约束。 下表列出了六种类型的约束:
where T:结构(类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。)
class MyClass<U> where U : struct///约束U参数必须为“值 类型” { } public void MyMetod<T>(T t) where T : struct { }
where T:类(类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。)
class MyClass<U> where U : class///约束U参数必须为“引用类型” { } public void MyMetod<T>(T t) where T : class { }
where T:new()(类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。)
class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new() { // ... }
where T:<基类名>(类型参数必须是指定的基类或派生自指定的基类。)
public class Employee{} public class GenericList<T> where T : Employee
where T:<接口名称>(类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。)
/// <summary> /// 接口 /// </summary> interface IMyInterface { } /// <summary> /// 定义的一个字典类型 /// </summary> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TVal"></typeparam> class Dictionary<TKey, TVal> where TKey : IComparable, IEnumerable where TVal : IMyInterface { public void Add(TKey key, TVal val) { } }
where T:U(为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。也就是说T和U的参数必须一样)
class List<T> { void Add<U>(List<U> items) where U : T {/*...*
免责声明:本站发布的内容(图片、视频和文字)以原创、来自互联网转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系QQ:712375056 进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
Copyright © 2009-2021 56dr.com. All Rights Reserved. 特网科技 特网云 版权所有 珠海市特网科技有限公司 粤ICP备16109289号
域名注册服务机构:阿里云计算有限公司(万网) 域名服务机构:烟台帝思普网络科技有限公司(DNSPod) CDN服务:阿里云计算有限公司 中国互联网举报中心 增值电信业务经营许可证B2
建议您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流浏览器浏览本网站