c#2.0的新特性--泛型

c#2.0中引入了许多新的语言特性:比较重要的有4个,泛型(Generics)、匿名方法(Annorymous Methods)、迭代器(Iterators)、和局部类(Partial Types).
  泛型
  是c#2.0中最强大的功能。
  特点一:通过泛型可以定义类型安全的数据结构,而无需使用具体实际的数据类型,着能够显著提高性能并得到高质量的代码。在概念上,反省类似于C++模板,但是在实现和功能方面存在明显差异。
  特点二:泛型通过把类型参数化来达到代码重用的目标,这一特性可以应用在类、结构、接口、委托、方法的设计之中。泛型除了可以大幅提高代码复用性外,
  特点三:还可以提供编译期间的类型检查,减少不必要的显式类型转换,减少不必要的装箱操作,从而提高应用程序的运行效率。
  1. 引入泛型的原因:
   一般情况下,在通用的数据结构中(例如Stack,List,Dictionory等)存储的数据,要求必须有相同的数据类型。如果必须存储不同类型的数据,那么唯一的方法就是将所有的数据首先装箱为object 类型,然后再存储。
  例如,下面的Stack类将其所有的数据存储在一个object类型的数组中,该类型的两个方法分别使用object来获取和返回数据:

public class Stack
{
    object[] items;
    public void Push(object item) {...}
    public object Pop() {...}
}

这样做的缺点:
第一是性能:根据装箱和堆栈的功能,使用Push方法能够想堆栈中压入任何类型的值,然而,再重新获取堆栈中的数据值时必须在使用Pop方法拆箱的同时,使用显式类型转换得到合适的数据类型。这种装箱和拆箱的操作增加了执行的负担,因为它带来了动态内存分配和运行时类型检查。
第二是类型安全。因为编译器允许在任何类型和Object之间进行强制类型转换,所以将造成编译时类型安全的不足。主要是Stack类无法强制设置堆栈中的数据类型。
第三是工作效率。编写类型特定的数据结构以及冗繁的的转换代码是一项乏味重复的且易于出错的工作 。
为了有效解决以上问题,c#2.0引入了泛型。
2.泛型概述
  泛型常见于集合应用中,在。net2.0框架的类库中,提供了一个新的名空间System.Collections.Generic,其中包含了一些新的基于泛型的容器类,例如,System.Collectinos.Generic.Stack,System.Collections.Dictionary,Collections.Generic.List,System.Collections.Generic.Queue
等,这些类库可以在集合中实现泛型。
   以堆栈中实现泛型为例
   Stack类示意代码:
   public class Stack<T>
   {
        T[] items;
        int count;
        public void Push(T item) {...}
        public T Pop() {...}
    }
   Stack类应用代码:
    //实例化Stack类
    Ststem.Collections.Genric.Stack<string> stringStack = new System.Collections.Generic.Stack<string>;
   //增加数据
   stringStack.Push("硬盘");
   stringStack.Push("声卡");
   stringStack.Push("电源");
   //转换为数组
   Araay stringArray;
   stringArray = stringStack.ToAraay();
   //显示数据
   foreach(string item in stringArray)
{
   Console.WriteLine(item);
}

3.约束
为了提供更强大的编译期间的类型检查和减少类型转换,c#允许一个可选的为每个类型参数提供的约束列表。一个类型参数的约束指定了一个类型必须遵守的要求,使得这个类型参数能够作为一个变量来使用。约束有关键字where来声明,后跟类型参数的名字,再后是一个类或接口 类型的列表,或者构造器约束new().
比如要想使Dictionary<K,V>类能保证键值始终实现IComparable接口,类的声明中应该对类型参数K指定一个约束
public class Dictionary<K,V> where K: IComparable
{

            public void Add(K key, V value)
            {
                  ...
                  if(key.CompareTo(x) < 0 )   {....}
                  ...
            }
}
类型参数约束的使用要小心。尽管它们提供了更强大的编译期间的类型检查并在一些情况下改进了性能,它还是限制了泛型类型的使用。比如一个泛型类List<T>可能约束T实现IComparable接口,以便Sort方法能够比较其中的元素。然而这么做的结果使得List<T>不能用于那些不能实现IComparable接口的类型,尽管在某些情况下Sort方法从没有被实际调用过。

4。泛型类型的成员

class C<V>
{
    public V f1; //声明字段
    public D<V> f2; //作为其他泛型类型 的参数
    public C<V x>
    {
       this.f1 = x;
    }
}

    泛型类型的成员可以使用泛型类型声明中的类型参数。但类型参数如果没有任何约束,则只能在该类型上使用从System.Object继承的共有成员。

5.泛型接口

interface IList<T>
{
    T[] GetElements();
}
interface IDictionary<K,V>
{
    void Add(K key,V value);
}
//泛型接口的类型参数要么已实例化
//要么来源于实现类声明的类型参数

class List<T>:IList<T>,IDictionary<int,T>
{
    public T[] GetElements{}
    {
       return null;
    }
    public void Add(int index,T value){}
}

6.泛型委托

delegate bool Predicate<T>(T value);
class X
{
     static bool F(int i){...}
     static bool G(string s){...}
     static void Main()
     {
          Predicate<string> p2 = G;
          Predicate<int> p1 = new Predicate<int>(F);
     }
}
     泛型委托支持返回值和参数哂纳感应用参数类型,这些参数类型同样可以附带合法的约束。

7.泛型方法的简介

    C#泛型机制只支持“在方法声明上包含类型参数” -- 即泛型方法。

    C#泛型机制不支持在除方法外的其他成员(包括属性、事件、索引器、构造器、析构器)的声明上包含类型参数,但这些成员本身可以包含在泛型类型中,并使用泛型类型的类型参数。

    泛型方法既可以包含在泛型类型中,也可以包含在非泛型类型中。

8.泛型方法的声明与调用

public class Finder
{
    // 泛型方法的声明
    public static int Find<T>(T[] items,T item)
    {
        for(int i=0;i<items.Length;i++)
        {
             if(items[i].Equals(item)
            {
                return i;
            }
        }
        return -1;
    }
}

// 泛型方法的调用
int i = Finder.Find<T>(new int[]{1,3,4,5,6,8,9},6);

泛型编程

9.泛型方法的重载

class MyClass
{
    void F1<T>(T[] a,int i); // 不可以构成重载方法
    void F1<U>(U[] a,int i);

    void F2<T>(int x); // 可以构成重载方法
    void F2(int x);

    void F3<T>(T t) where T : A; // 不可以构成重载方法
    void F3<T>(T t) where T : B;
}

10.泛型方法的重写

abstract class Base
{
    public abstract T F<T,U>(T t,U u) where U : T;
    public abstract T G<T>(T t) where U : IComparable;
}
class Derived:Base
{
    // 合法的重写,约束被默认继承
    public override X F(X,Y)(X x,Y y){}

    // 非法的重写,指定任何约束都是多余的
    public override T G<T>(T t) where T : Comparable{}
}

11.泛型约束简介

    C#泛型要求对"所有泛型类型或泛型方法的类型参数"的任何假定,都要基于"显式的约束",以维护C#所要求的类型安全.

    "显式约束"有where字句表达,可以指定"基类约束","接口约束","构造器约束","值类型/引用类型约束"共四中约束.

    "显示约束"并非必须,如果没有指定"显式约束",泛型类型参数将只能访问System.Object类型中的公有方法.

基类约束

class A
{
    public void F1(){}
}
class B
{
    public void F2(){}
}

class C(S,T)
where S:A // S继承自A
where T:B // T继承自B
{
    // 可以在类型为S的变量上调用F1
    // 可以在类型为T的变量上调用F2
}

接口约束

interface IPrintable{coid Print();}
interface IComparable<T>{int CompareTo(T v);}
interface IKeyProvider<T>{T HetKey();}

class Dictionary<K,V>
   where K:IComparable<K>
   where V:IPrintable,IKeyProvider<K>
{
    // 可以在类型为K的变量上调用CompareTo
    // 可以在类型为V的变量上调用Print和GetKey
}

构造器约束

class A
{
    public A(){}
}
class B
{
    public B(int i)()
}

class C<T>
   where T:new()
{
    // 可以在其中使用T t = new T();
}
C<A> c = new C<A>(); // 可以,A有无参数构造器
C<B> c = new C<B>(); // 错误,B没有无参数构造器

值类型/引用类型约束

public struct A{...}
public class B{...}

class C<T>
where T : struct
{
// T在这里面是一个值类型
}
C<A> c = new C<A>(); // 可以,A是一个值类型
C<B> c = new C<B>(); // 错误,B是一个引用类型

12.总结

    C#的泛型能力有CLR在运行时支持,它既不同于c++在编译时所支持的静态模板,也不同于java在编译器层面使用"檫拭法"支持的简单的类型.

    C#的泛型支持包括类,结构,接口,委托共四种泛型类型,以及方法成员.

    C#的泛型采用"基类,接口,构造器,值类型/引用类型"的约束方式来实现对类型参数的"显式约束",它不支持C++模板那样的基于签名的显式约束.

转载于:https://www.cnblogs.com/zgqys1980/archive/2006/10/10/525529.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/412053.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构建之法与博客首秀

问题一&#xff1a;软件的安全功能是指什么呢&#xff1f; 我看了《构建之法》第七页对飞机安全功能的的描述&#xff0c;想知道在软件中是否有类似飞机的安全功能&#xff1f;如果有&#xff0c;具体是指什么功能呢&#xff1f;我在查阅资料后只找到对软件安全的的总结(软件安…

java接口import_深入理解Java架构师在组件注册@Import导入容器(ImportSelector接口)的神操作!...

ImportSelector&#xff1a;返回需要导入的组件的全类名数组创建一个实现了ImportSelector接口的类&#xff0c;然后让入Import中。ImportSelector的实现类包含了所有需要导入到容器中的组件。public class StuConfigurationImportSerlect implements ImportSelector {Override…

[vue] 说说你觉得认为的vue开发规范有哪些?

[vue] 说说你觉得认为的vue开发规范有哪些&#xff1f; 风格指南个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

[vue] vue性能的优化的方法有哪些?

[vue] vue性能的优化的方法有哪些&#xff1f; Vue 项目性能优化 — 实践指南&#xff08;网上最全 / 详细&#xff09; 前言 Vue 框架通过数据双向绑定和虚拟 DOM 技术&#xff0c;帮我们处理了前端开发中最脏最累的 DOM 操作部分&#xff0c; 我们不再需要去考虑如何操作 D…

JavaScript小技巧一

事件源对象 event.srcElement.tagName event.srcElement.type 捕获释放 event.srcElement.setCapture(); event.srcElement.releaseCapture(); 事件按键 event.keyCode event.shiftKey event.altKey event.ctrlKey 事件返回值 event.returnValue 鼠标位置 event.x event.y 窗…

java builder pool_每周10道Java面试题:String, String Pool, StringBuilder

每周10道 Java 面试题由 ImportNew 整理编译自网络。1. 写出下面代码的运行结果。int src 65536;Integer dst new Integer(65536);System.out.println(src dst);System.out.println(dst.equals(src));答案&#xff1a; true true考点&#xff1a; Integer 的 equals 实现。查…

Transactional cannot be resolved to a type

SpringBoot整合Mybatis时遇到“ Transactional cannot be resolved to a type ” &#xff0c;以为是没有导入相应的包 “ import org.springframework.transaction.annotation.Transactional; ” &#xff0c;导入发现还是报错&#xff0c;在Stack Overflow上找到解决办法。在…

[vue] 有在vue中使用过echarts吗?踩过哪些坑?如何解决的?

[vue] 有在vue中使用过echarts吗&#xff1f;踩过哪些坑&#xff1f;如何解决的&#xff1f; vue 没用过echarts react到是用过 不过我想应该差不多 &#xff0c;多注意dom的渲染时机 和chart的实例化时机 在相应的生命周期方法中做操作。结合强制刷新 应该就能解决大部分问题…

终于通过了~

申请博客园的blog真TM费尽&#xff0c;提交了N次申请都没成功&#xff0c;说什么“期待你更详细的申请理由”&#xff0c;我靠&#xff0c;管理还真TMD严格啊。 不过觉得这个blog做的还真不错&#xff0c;而且人也比较多&#xff0c;hoho&#xff5e;。 以后偶会…

将字符串中的字符按Z字形排列,按行输出

示例1&#xff1a; Input: s "PAYPALISHIRING", numRows 3 Output: "PAHNAPLSIIGYIR" 示例2&#xff1a; Python解决方案&#xff1a; def convert(self, s, numRows):""":type s: str:type numRows: int:rtype: str"""…

[vue] 说说你对单向数据流和双向数据流的理解

[vue] 说说你对单向数据流和双向数据流的理解 单向数据流&#xff1a;所有状态的改变可记录、可跟踪&#xff0c;源头易追溯&#xff1b;所有数据只有一份&#xff0c;组件数据只有唯一的入口和出口&#xff0c;使得程序更直观更容易理解&#xff0c;有利于应用的可维护性&…

值类型和引用类型

值类型&#xff08;如 char、int 和 float&#xff09;、枚举类型和结构类型。 引用类型包括类 (Class) 类型、接口类型、委托类型和数组类型。 值类型与引用类型的区别在于值类型的变量直接包含其数据&#xff0c;而引用类型的变量则存储对象引用。 对于引用类型&#xff0c;两…

java设计模式在项目中的使用_SpringMVC项目里,有必要使用一些设计模式吗?

背景为了兼容多种业务&#xff0c;想在项目中使用一些设计模式&#xff0c;以便于管理。例如&#xff0c;我需要创建用户并返回userid&#xff0c;每种业务创建的方式都不一样。我选取了“适配器模式”&#xff0c;但是我发现&#xff0c;在springmvc的管理下&#xff0c;常常需…

大型网络架构变迁和知识图谱

——仅供个人学习使用&#xff0c;如有侵犯版权&#xff0c;请作者联系我&#xff0c;立马处理。 【前端页面缓存】 sessionStorage,localStorage,userData,cookie, [sessionStorage] h5后出现的新技术&#xff0c;这个生命周期短&#xff0c;当页面关闭后&#xff0c;存储资源…

[vue] SSR解决了什么问题?有做过SSR吗?你是怎么做的?

[vue] SSR解决了什么问题&#xff1f;有做过SSR吗&#xff1f;你是怎么做的&#xff1f; SSR server side render服务端渲染&#xff0c;解决spa应用缺点的首屏加载速度慢、不利于SEO问题个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c;…

常用英语对话

妙语佳句(1)  1. It‘s not like that. 不是那样的   It‘s not like that.这句话是用来辟谣的。当别人误会了一件事的来龙去脉&#xff0c;你就可以跟他说It‘s not like that.「不是那样的。」当然随着语气及情境的不同&#xff0c;It‘s not like that.这句话也有可能是…

H265摄像头如何实现网页直播

介绍 目前安防监控行业&#xff0c;基本所有的摄像头都支持H264编码&#xff0c;但是已经有部分摄像头开始支持H265&#xff0c;并且支持H265的摄像机已经越来越多。H265相比H264有着很多优势&#xff0c;是压缩更高&#xff0c;网络传输消耗的带宽更小&#xff0c;相同码率下H…

java获取xls在项目路径_JAVA获取项目路径

在jsp和class文件中调用的相对路径不同。 在jsp里&#xff0c;根目录是WebRoot 在class文件中&#xff0c;根目录是WebRoot/WEB-INF/classes 当然你也可以用System.getProperty("user.dir")获取你工程的绝对路径。另:在Jsp,Servlet,Java中详细获得路径的方法!1.jsp中…

[vue] 你有自己用vue写过UI组件库吗?

[vue] 你有自己用vue写过UI组件库吗&#xff1f; {{item.title}}<dl v-if"item.list.length > 0"><dd v-for"(item2,index2) in item.list" :index"index2" :key"item2.title"><router-link :to"item2.route&…

在字符串中使用引号()等字符 需要用转义字符\ 例如

Response.Write("<script language\"javascript\">alert(输入的时间格式不正确&#xff01;);</script>"); 转载于:https://www.cnblogs.com/cuihongyu3503319/archive/2006/11/06/551830.html