C#2.0泛型

泛型是什么

一种类型占位符,或称之为类型参数。我们知道在一个方法中,一个变量的值可以作为参数,但其实这个变量的类型本身也可以作为参数。泛型允许我们在调用的时候再指定这个类型参数是什么。在.net中,泛型能够给我们带来的两个明显好处是——类型安全和减少装箱、拆箱。

 

泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱。

      很多非泛型集合类都有对应的泛型集合类,我觉得最好还是养成用泛型集合类的好习惯,他不但性能上好而且 功能上要比非泛型类更齐全。下面是常用的非泛型集合类以及对应的泛型集合类:

    

非泛型集合类泛型集合类
ArrayListList<T>
HashTableDIctionary<T>
QueueQueue<T>
StackStack<T>
SortedListSortedList<T>

最显著的一点就是它参数化了类型,把类型作为参数抽象出来,从而使我们在实际的运用当中能够更好的实现代码的重复利用,同时它提供了更强的类型安全,更高的效率,不过在约束方面,它只支持显示的约束,这样在灵活性方面就显得不是那么好了.我觉得它之所以能够提供更高的效率是因为泛型在实例化的时候采用了"on-demand"的模式,即按需实例化,发生在JIT(Just In Time)编译时.
      下面来看如何定义一个泛型类,很简单,你只需要意识到一点,在这里,类型已经被参数化了:

using System;
using System.Collections.Generic;
using System.Text;

namespace GenericTest
ExpandedBlockStart.gifContractedBlock.gif
{
    
class Program
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//使用string,int来实例化Test<T,S>类
            Test<stringint> t = new Test<stringint>("SHY520",22);

            
//调用泛型类中的方法
            t.SetValue();
        }

    }


ExpandedSubBlockStart.gifContractedSubBlock.gif    
/// <summary>
    
/// 定义一个泛型类,该类有两个类型参数,分别是T,S
    
/// http://pw.cnblogs.com
    
/// </summary>
    
/// <typeparam name="T">类型参数</typeparam>
    
/// <typeparam name="S">类型参数</typeparam>

    public class Test<T,S>
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
//泛型类的类型参数可用于类成员
        private T name;
        
private S age;

        
public Test(T Name,S Age)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
this.name = Name;
            
this.age = Age;
        }


        
public void SetValue()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            Console.WriteLine(name.ToString());
            Console.WriteLine(age.ToString());
        }

    }

}


        上面的例子不是很恰当,目的是让初学泛型的你了解一下泛型的定义及实例化方法,如上,我们定义了一个泛型类,那么如何实现泛型类的继承呢?这里需要满足下面两点中的任何一点即可:
1、泛型类继承中,父类的类型参数已被实例化,这种情况下子类不一定必须是泛型类;
2、父类的类型参数没有被实例化,但来源于子类,也就是说父类和子类都是泛型类,并且二者有相同的类型参数;

    //如果这样写的话,显然会报找不到类型T,S的错误
ExpandedBlockStart.gifContractedBlock.gif
    public class TestChild : Test<T, S> { }

    
//正确的写法应该是
ExpandedBlockStart.gifContractedBlock.gif
    public class TestChild : Test<stringint>{ }

ExpandedBlockStart.gifContractedBlock.gif    
public class TestChild<T, S> : Test<T, S> { }

ExpandedBlockStart.gifContractedBlock.gif    
public class TestChild<T, S> : Test<String, int> { }

接着我们来看看泛型接口,其创建以及继承规则和上面说的泛型类是一样的,看下面的代码:
    public interface IList<T> 
ExpandedBlockStart.gifContractedBlock.gif    
{
        T[] GetElements();
    }
 
    
public interface IDictionary<K,V>             
ExpandedBlockStart.gifContractedBlock.gif    
{
        
void Add(K key, V value); 
    }
 

    
// 泛型接口的类型参数要么已实例化
    
// 要么来源于实现类声明的类型参数
    class List<T> : IList<T>, IDictionary<int, T> 
ExpandedBlockStart.gifContractedBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public T[] GetElements() return null; }
        
public void Add(int index, T value) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        

        }

    }


在来看一下泛型委托,首先我们定义一个类型参数为T的委托,然后在类中利用委托调用方法:
using System;
using System.Collections.Generic;
using System.Text;

namespace GenericTest
ExpandedBlockStart.gifContractedBlock.gif
{
    
//定义一个委托,类型参数为T,返回值类型T
    
//泛型委托支持在返回值和参数上应用类型参数
    delegate string GenericDelete<T>(T value);

    
class test
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
static string F(int i) return "SHY520"; }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
static string G(string s) return "SHY520"; }

        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            GenericDelete
<string> G1 = G;
            GenericDelete
<int> G2 = new GenericDelete<int>(F);
        }

    }
 
}


        我们再来看泛型方法,C#的泛型机制只支持在方法申明上包含类型参数,也即是泛型方法。特别注意的是,泛型不支持在除了方法以外的其他类/接口成员上使用类型参数,但这些成员可以被包含在泛型类型中,并且可以使用泛型类型的类型参数。还有一点需要说的就是,泛型方法可以在泛型类型中,也可以存在于非泛型类型中。下面我们分别看一下泛型类型的申明,调用,重载和覆盖。

using System;
using System.Collections.Generic;
using System.Text;

namespace GenericTest
ExpandedBlockStart.gifContractedBlock.gif
{
    
class GenericClass
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
//申明一个泛型方法
        public T getvalue<T>(T t)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return t;
        }


        
//调用泛型方法
        
//注意:在调用泛型方法时,对泛型方法的类型参数实例化
        public int useMethod()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return this.getvalue<int>(10);
        }


        
//重载getvalue方法
        public int getvalue(int i)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return i;
        }

    }


    
//下面演示覆盖
    
//要注意的是,泛型方法被覆盖时,约束被默认继承,不需要重新指定约束关系
    abstract class Parent
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
public abstract K TEST<K, V>(K k, V v) where K : V;

    }


    
class Child : Parent
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
public override T TEST<T, S>(T t, S s)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return t;
        }

    }

}


        最后我们来看一下泛型中的约束:
        C#中的泛型只支持显示的约束,因为这样才能保证C#所要求的类型安全,但显示的约束并非时必须的,如果不加约束,泛型类型参数将只能访问System.Object类型中的公有方法。“显式约束”由where子句表达,可以指定“基类约束”,“接口约束”,“构造器约束”,“值类型/引用类型约束”共四种约束。下面的例子来源于李建忠老师的讲座PPT。
1、基类约束:

ExpandedBlockStart.gifContractedBlock.gif    class A public void F1() {} } 
ExpandedBlockStart.gifContractedBlock.gif    
class B public void F2() {} } 
    
class C<S,T> 
    where S: A 
// S继承自A 
    where T: B // T继承自B 
ExpandedBlockStart.gifContractedBlock.gif
    
    
// 可以在类型为S的变量上调用F1,
    
// 可以在类型为T的变量上调用F2 
    }
 

2、接口约束
ExpandedBlockStart.gifContractedBlock.gif    interface IPrintable void Print(); 
    }

ExpandedBlockStart.gifContractedBlock.gif    
interface IComparable<T> int CompareTo(T v);}
ExpandedBlockStart.gifContractedBlock.gif    
interface IKeyProvider<T> { T GetKey(); }
    
class Dictionary<K,V> 
    where K: IComparable
<K> 
    where V: IPrintable, IKeyProvider
<K> 
ExpandedBlockStart.gifContractedBlock.gif    

    
// 可以在类型为K的变量上调用CompareTo, 
    
// 可以在类型为V的变量上调用Print和GetKey 
    }

3、构造器约束
ExpandedBlockStart.gifContractedBlock.gifclass A public A() { } } 
ExpandedBlockStart.gifContractedBlock.gif
class B public B(int i) { } } 
class C<T> 
where T : 
new() 
ExpandedBlockStart.gifContractedBlock.gif

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

4、值/引用类型约束
ExpandedBlockStart.gifContractedBlock.gifpublic struct A {  } 
ExpandedBlockStart.gifContractedBlock.gif
public class B {  } 
class C<T> 
where T : 
struct 
ExpandedBlockStart.gifContractedBlock.gif

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

转载于:https://www.cnblogs.com/guodapeng/archive/2009/05/30/1492383.html

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

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

相关文章

css行高line-height的一些深入理解及应用

1. 一些字面意思 “行高”是指两行文字间基线之间的距离。基线是在英文字母中用到的一个概念&#xff0c;我们刚学英语的时使用的那个英语本子每行有四条线&#xff0c;其中底部第二条线就是基线&#xff0c;是a,c,z,x等字母的底边线。下图的红色线即为基线 2. line-height与l…

echarts使用大总结

echarts图表x轴数据太多显示不全的问题 问题如图&#xff0c;x轴数据条数过多可能导致x轴显示不全&#xff0c;开始我使用下面方法 xAxis: {type: "category",min: min,max: max,data:time,axisLabel: {interval:num,//interval为x轴两相邻数据之间所包含数据条数&a…

宏定义中##和#的作用

From: http://blog.chinaunix.net/space.php?uid16135252&doblog&id2752917 内核中有很多的宏定义&#xff0c;在宏定义define中经常看到两个字符串##和#&#xff0c;这里把它的用法做一下说明&#xff1a; ##是一个连接符号&#xff0c;用于把参数连在一起 …

我对CSS vertical-align的一些理解与认识(一)

1. vertical-align一大堆乱七八糟的属性 有句俗语叫做“见多不怪”&#xff0c;我估摸着这些top,bottom属性大家都见过&#xff0c;没啥看头&#xff0c;没啥说头。老实讲&#xff0c;我看到这些养臭虫的属性也头疼&#xff0c;所以&#xff0c;忘了他们&#xff0c;我们说点有…

@Repository , @Service , @Controller 和 @Component

用Spring MVC时Controller注解的类将变成一个Spring MVC的控制器. 不用Spring MVC的情况下, 这四个注解没有区别. 根据注解的语义, 注解在类上面可以提高代码的可读性.Repository代表仓库. 一般注解在DAO实现类上, 别人看代码时, 就知道这个类是一个跟数据存储有关的类. Servic…

vue的token刷新处理

前言 以token处理登录的web系统&#xff0c;一般会有两个token&#xff1a;access-token和refresh-token。 node.js中&#xff0c;一般用jsonwebtoken这个模块。 access-token&#xff0c;是用户输入登录的账号密码&#xff0c;后台去db验证然后颁发的&#xff0c;它一般记录…

我对CSS vertical-align的一些理解与认识(二)

1. 我对不同浏览器解析vertical-align属性的理解 在上集中&#xff0c;在最后提供的实例中&#xff0c;vertical-align:middle实际上应该是与后面的文字是独立的&#xff0c;毫无关联&#xff0c;就是说vertical-align无论是什么&#xff0c;都不影响文字在box中的位置&#x…

request_do?send方法

Ruby中 respond_to? 和 send 的用法php?nameRuby" class"t_tag">Ruby中 respond_to? 和 send 的用法[收藏] Ruby中的字符串与符号 如同其他的OO语言一样&#xff0c;在ruby中&#xff0c;通过给对象发送消息&#xff0c;来完成对象的功能&#xff0c;比如…

Vue中token刷新及token过期的实现

总&#xff1a;通过axios&#xff0c;vuex&#xff0c;及自定义的方法实现。 以下是思路&#xff1a; 1.做token刷新必不可少的是&#xff0c;token&#xff08;请求时的token&#xff09; / refresh_token&#xff08;刷新token时用的refresh_token&#xff09; / resetTime&a…

Source Code Library 源代码收集器

对于程序员来说&#xff0c;收集、整理一些常用的源代码是经常性的工作&#xff0c;但很多时候&#xff0c;随着收集的代码、文档、压缩包的增长&#xff0c;也会产生另一个问题&#xff1a;那就是如何快速找到所需要的内容。 这个问题曾经困扰着我&#xff0c;后来我开始使用&…

VC2010如何给ActiveX添加事件

利用VC开发ActiveX时&#xff0c;需要给控件添加标准事件或自定义事件&#xff0c;在VC6中有多种方法&#xff1a; 一、按Ctrl W 打开类向导&#xff0d;&#xff1e;切换到“ActiveX Events"&#xff0d;&#xff1e;Add Event...&#xff0c;如图&#xff1a; 二、右…

css动态设置宽高

css 中可以使用 calc() 来动态设置宽高&#xff0c;但是&#xff0c;在表达式中运算符的前后必须要有空格 height:calc(100vh - 80px);

Windows Runtime (RT)

学了sl for wp 开发了1年都没入门&#xff0c;只能说自己的学习欲望太低了。 今天偶然才发现wrt 跟 .net 是2个东西... orz。 得抛弃 sl &#xff0c;wrt才是未来的主流吧... 这篇文章不错 http://www.dotblogs.com.tw/regionbbs/archive/2011/09/18/introducing.windows.runti…

产业链没有阴谋

IBM将PC甩给联想&#xff0c;是IBM的产业链阴谋吗&#xff1f;上个星期在客户的研讨会上有人这样问我。提问的这位朋友刚刚看过郎咸平的《产业链阴谋》&#xff0c;认为我们之所以处于“6 1”的低端&#xff0c;就是中了跨国公司的诡计&#xff0c;他们想进入高端&#xff0c;…

CSS中height:100%和height:inherit的异同

1. height:100%和height:inherit的异同 1.1 兼容性差异 height:100% IE6 √ height:inherit IE8 √ 1.2 大多数情况作用是一样的 除去兼容性&#xff0c;大多数情况下&#xff0c;两者作用是一样的&#xff0c;甚至都很难想出不一样的理由 父容器height: auto&#xff0c…

手机端双击页面放大的问题

制作手机端页面的时候我们都会加入一个meta标签&#xff0c; 该meta标签的作用是让当前viewport的宽度等于设备的宽度&#xff0c;同时不允许用户手动缩放。 其中 maximum-scale为允许用户的最大缩放值&#xff0c;user-scalable为是否允许用户进行缩放&#xff0c;yes(默认)…