C#泛型探究(自学篇)

C#泛型探究(自学篇)
C#泛型探究(自学篇)

前言

前几日同学告诉我他老师告诉他,泛型是定义一种通用的方法,至于为什么用泛型他的答

案还是定义一种通用的方法,当时我也没有学,还不懂啦,毕竟人家是计算机专业的科班生,我当

然没有发言权,只是怀疑的记下了这个错误的结论打算以后看看是不是对的,这两天算是把泛型学

了一下,其实它定义的不只是方法,自己感觉他就是一种规范代码执行效率的模版,这样极不容易

出错,并把我们常用的箱拆箱操作过程给省了,提高了编译器的执行效率,。至于为什么用泛型这

个我貌似已经说明白了,泛型多用于集合类操作,我在这里随意的拿出C#定义的ArrayList的

Add方法的定义我们一起看看:

public virtual int Add(

Object value

)

可以看出我们可以往ArrayList里添加任何类型的元素,假如有一个string类型的str字符

串它在添加到ArrayList lib的过程中实际进行了装箱操作,即object

value=str;那么我

们在获取这个值得时候必须这样使用string s=(string)lib[0];不能遗漏(string)否则会提示你,

错误1无法将类型“object”隐式转换为“string”。存在一个显式转换(是否缺少强制转换?)

但是你假如这样写:int a=(int)lib[0];程序在运行前是无法报错的,只要一旦运行就会出

现异常,而这些错误都可以利用泛型轻松搞定,让你在编译时就可以发现错误,具体的就看你怎么

领悟了,我在文章里没有写任何定义的语法格式,因为这个既没必要说,这是常识,出来混这些迟

早是要明白的,呵呵。玩笑啦......欢迎新手同学来我的博客交流学习,我也希望你们可以为我敞

开心怀,因为我既不是计算机专业的学生,甚至上了大学我已经不再是理工类的学生。我无意扎进了

文科专业去叱咤风云啦,哎,这个文科专业名字太有点科学技术的味道了。我喜欢

........

我的博客地址是:https://www.360docs.net/doc/424794218.html,

关于泛型的几个重要概念:

泛型类型形式参数(类型形参):是泛型类型或泛型方法等定义中的

占位符。类型形参一般以大写字母T开头,如果只有一个类型形参,

一般用T来表示。

构造泛型类型(构造类型):是为泛型类型定义的泛型类型参数指定

类型得到的结果。

泛型类型实际参数(类型实参):是替换泛型形参的任何类型。

约束:是加在泛型类型参数上的限制。使用泛型类型的客户端不能替

换不满足这些约束的类型参数。

泛型类:

泛型类型可以根据类型形参的数目进行““重载

重载””,也就是两个类型声

泛型类型可以根据类型形参的数目进行

明可以使用相同的标识符,只要这两个声明具有不同数目的类型参数

即可。例如:

class A{};

class A{};

class A{};

此时如果我们在定义一个class A;或{}class A{};就会

报错,为什么呢,原因很简单,这就是我前面提到的这些大写字母本

身没有多大意义,只是一个(等待替换的未知实际参数的)占位符即

类型参数。

非泛型类类声明的中指定的基类或者基接口可以是构造类型但必须是封闭构造类型。(也就.NET的CLR的JIT将泛型IL和元数据转换

为本机代码,并在该过程中将类型形参替换为类型实参)但是不能是

类型形参,而在基类或者基接口的作用域中可以包含类型形参。下面

我做下详细解释,例如:

using System;

namespace Generic

{

class A

{

public virtual void F1(U a,V b)

{

Console.WriteLine("F1中包含的参数的CTS类型为:\n{0}\n{1}", a.GetType(), b.GetType());

}

}

interface I

{

T F2(T x);

//基类或者基接口的作用域中可以包含类型形参

}

class ChildTest1:A

{

//重写基类的F1方法

public override void F1(string a,string b)

{

Console.WriteLine(a+b);

}

}

class ChidTest2:A,I

{

//实现基接口中的方法

public string F2(string x)

{

return("F2包含的参数值为:"+x);

}

//该类隐藏了基类的F1方法

public new void F1(string a,int b)

{

Console.WriteLine("ChidTest2类隐藏了基类的F1方法");

}

}

//测试类

class Test

{

static void Main(string[]args)

{

//泛型类A只有初始化类型参数后才有意义

Aa=new A();//注意:其中A为构造类型,也就是初始化类型形参

ChildTest1cd1=new ChildTest1();

ChidTest2cd2=new ChidTest2();

a.F1("123",123);

cd1.F1("ChildTest1类重写了基类的","F1方法");

cd2.F1("123",123);

Console.WriteLine(cd2.F2("123"));

Console.ReadKey(true);

}

}

}

在上面的代码中我只是介绍了非泛型类的继承,那么泛型类的继承是不是一样呢?这个大家可以先自己想一想,我在讲到泛型接口的时候会提到,下面继续说一下啊泛型类的成员的特点。

泛型类中所有的成员都可以直接作为构造类型或者构造类型的一部

分来使用包容类(enclosed class)中的类型形参。当公共语言运行时使用特定的封闭构造类型时,所出现的每个类型形参都被替换该构造类型提供的类型实参。例如:

using System;

namespace Generic

{

class A

{

//定义两个类型字段

public T a;//作为构造类型的一部分(成员)使用类型形参T

public Ab=null;//直接作为构造类型使用类型形参T

//实例构造函数,其中this是A的实例

public A(T x)

{

this.a=x;

this.b=this;

}

}

//测试类

class Test

{

static void Main(string[]args)

{

AA1=new A("Hello World");

Console.WriteLine(A1.a);

Console.WriteLine(A1.b.a);

AA2=new A(123);

Console.WriteLine(A1.a);

Console.WriteLine(A1.b.a);

Console.ReadKey(true);

}

}

}

可能这里有的同学不理解我说的封闭构造类型,我前面提到了

构造类型,我在这里在解释一下,例如A和A都是构造

类型,我们将(使用一个或多个类型形参的构造类型)A称为开放

构造类型;将(不实用类型形参(即使用实参)的构造类型)A称为封闭构造类型。

此外对于上面的代码我可以这样解释:即构造类型成员可以直

接或一部分作为开放构造类型使用类型形参,可以直接或一部分作为

封闭构造类型使用类型实参。

泛型接口

我先前提到过类型形参只是一个(等待替换的未知实际参数的)占位

符。那么如果这样接口interface I,interface I,interface I

实是一样的,同时和泛型类一样,可以根据类型形参的数目进行“重

载”,也就是两个类型声明可以使用相同的标识符,只要这两个声明

具有不同数目的类型参数。

};interface I{}这个是合

那么我们这样想,假如我要用一个类实现interfaceI

I

interface I

interface I

{

void F();

}

,我们是否可以使用形如:

class A:I,I//之后替换为interface I和interface I

{

void I.F()

{

}

void I.F()

{

}

}

这样编译器便会提示:

,

错误1

“Generic.A”不能同时实现“Generic.I”和“Generic.I”,原因是它们对于某些类型形参替换可以进行统一

也就是说,当使用泛型类实现泛型接口必须试所有可能的泛型接

口的构造类型(例如I)保持唯一,否则编译器无法确定该为某

个泛型接口的显示成员调用那个方法。可能以为I就是I)。

但是我们可以将不同继承级别指定的接口进行统一。例如:

interface I

{

void F();

}

class Base:I

{

void I.F()

{

Console.WriteLine("I.F()");

}

}

class Derived:Base,I

{

void I.F()

{

Console.WriteLine("I.F()");

}

}

class Test

{

public static void Main()

{

Itest1=new Base();

Itest2=new Derived();

test1.F();

test2.F();

Console.ReadKey();

Console.ReadKey();

}

}

从上面的代码可以看出,虽然Derived同时实现了I

I,test2.F()这里将调用I.F()的方法,实际上实在Derived中重新实现了I.

这里我们再回到上面我说泛型类的时候,泛型类继承的特点,这里一

看代码便已明了,泛型类继承的基类或者基接口可以是开放的构造类

型也可以使封闭的构造类型(我已测试,这个大家也可以测试一下、)。

泛型方法

泛型方法可以在类,结构,接口声明中声明,这些类,结构,

接口本身可以是泛型或者非泛型。

1.如果泛型方法在泛型类型中声明,则方法体可以同时引用该

方法的类型形参和包含该方法的声明(泛型类,结构,接口)的

类型形参。

2.类型形参可以作为返回类型或形参的类型。

3.方法的类型形参的名称不能与相同方法中的普通形参的名称相同。

下面我对上面的问题一一解释:

class A

{

public static void Print(U a,V b,T c)

{

Console.WriteLine("{0}\n{1}\n{2}", a.GetType(), b.GetType(), c.GetType()); }

}

class Test

{

public static void Main()

{

A.Print("str",125.25m,15);

Console.ReadKey();

}

}

对应问题1

class A

{

public static U Print(U a,V b)

{

return a;

}

}

class Test

{

public static void Main()

{

Console.WriteLine(A.Print("str",125));

Console.ReadKey();

}

}

对应问题2

public static U Print(U U,V b)假如我们这里设置如此,语法没有错误,但是编译器运行

时会提示:

错误1

“U”:参数或局部变量不能与方法类型形参同名

对应问题3

此外泛型方法除了非泛型方法的签名(由方法的名称和他的每一个形

参(按从左到右的顺序)的类型和种类(值,引用,输出)组成。)

要素外,泛型方法还包括泛型类型形参的数目和类型形参的序号位置

(按从左到右),记住前面说过的类型形参只是个占位符。例如:

T F(T a,int b)

{

return a;

}

void F(){}

string F(string a,int b){};

}

上面的代码由于方法名相同,但是不会报错,为什么呢,这就涉及到

方法的重载策略,但是假如出现:

public void F(U a,int b){},那么就会报错,因为这两个泛型类型形参的数目和类型形参的序号位置都是一样的。假如我在这样改一下:

public void F(int b,U a)

重载策略的衍生,其实是一样的原理。

泛型委托

这里普通的泛型委托和普通委托一样很简单,我来试着测试一下匿名

方法是不是也一样简单好了。

public delegate T Degle(int a,T b);

class Test

{

public static void Main()

{

Degledg=delegate(int a,string b)

{

return b;

};

Console.WriteLine(dg(125,"使用了匿名方法创建泛型委托"));

Console.ReadKey();

}

}

约束

在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类进行限制,如果客户端代码使用某个约束不允许的类型来实例化类,就会产生编译时错误。这种限制称为约束。约束是使用

如果要检泛型列表中的某个项以确定它是否有效,或者将它与其他某个项进行比较,则编译器必须在一定程度上保证它需要调用的运算符或方法将受到客户端代码可能指定的任何类型参数的支持。这种保证是通过对泛型类定义应用一个或多个约束获得的。例如,基类约束告诉编译器:仅此类型的对象或从此类型派生的对象才可用作类型参数。一旦编译器有了这个保证,它就能够允许在泛型类中调用该类型

的方法。首先我们先看一个(不使用约束的)例子:

using System;

using System.Collections;

namespace Generic

{

public class Student

{

private string name;

public string Name

{

set

{

name=value;

}

get

{

return name;

}

}

public Student(string s)

{

name=s;

}

}

public class Grade//定义一个年级类ArrayList names=new ArrayList(10);

public void Add(T t)

{

names.Add(https://www.360docs.net/doc/424794218.html,);//这里便会出错

}

public void Display()

{

foreach(string s in names)

{

Console.WriteLine(s);

}

}

}

public class Test

{

public static void Main()

{

Gradegn=new Grade();

gn.Add(new Student("小明"));

gn.Add(new Student("小花"));

gn.Add(new Student("阿猫"));

gn.Add(new Student("阿狗"));

Console.WriteLine("一年级的同学有:");

gn.Display();

}

}

}

运行就会提示:

错误1

“T”不包含“Name”的定义,并且找不到可接受类型为“T”的第一个参数的扩展方法“Name”

(是否缺少using指令或程序集引用?)

也就是说,我们在使用T为实际形参占位的时候,编译器运行到

names.Add(https://www.360docs.net/doc/424794218.html,);

例到底有没有Name属性,或者这个Name到底是字段还是属性呢?

程序是一步一步走的,他没有人的逻辑那样跳步完成某个推理,所以

这里就会报错,因此我们就应该提前告知编译器这里类型形参T所能

代表的具体范围,这样就可以解决问题了。

因此这里就引出了约束来轻松的解决这一问题。我们只需要修改一

句:public class Gradewhere T:Student我们在Grade的类中增加了约

束,修改以后程序就可以便已通过,因为我们已经告知编译器Grade

中的T是Student类或者派生自Student类的,所以可以使用

https://www.360docs.net/doc/424794218.html,属性。

using System;

using System.Collections;

namespace Generic

{

public class Student

{

private string name;

public string Name

{

set

{

name=value;

}

get

{

return name;

}

}

public Student(string s)

{

name=s;

}

}

public class Gradewhere T:Student {

ArrayList names=new ArrayList(10); public void Add(T t)

{

names.Add(https://www.360docs.net/doc/424794218.html,);//这里便会出错

}

public void Display()

{

foreach(string s in names)

{

Console.WriteLine(s);

}

}

}

public class Test

{

public static void Main()

{

Gradegn=new Grade();

gn.Add(new Student("小明"));

gn.Add(new Student("小花"));

gn.Add(new Student("阿猫"));

gn.Add(new Student("阿狗"));

Console.WriteLine("一年级的同学包括");

gn.Display();

}

}

}

可以对同一类型的参数应用多个约束,并且约束自身可以是泛型类

型,例如:

public class Gradewhere T:Student,IStudent,System.IComparable,new() {

//...

}

这里重要一点的就是new(),new约束指定泛型类声明中的任何类型

参数都必须有公共的无参数构造函数。如果要使用new约束,则该类

型不能为抽象类型。当泛型类创建类型的新实例,请将new约束应用

于类型参数,如下面的示例所示:

class ItemFactorywhere T:new()

{

public T GetNewItem()

{

return new T();

}

}

当与其他约束一起使用时,new()约束必须最后指定:

publicclass ItemFactory2

where T:IComparable,new()

{

}

通过约束类型参数,可以增加约束类型及其继承层次结构中的所有类

型所支持的允许操作和方法调用的数量。因此,在设计泛型类或方法时,

如果要对泛型成员执行除简单赋值之外的任何操作或调用

System.Object不支持的任何方法,您将需要对该类型参数应用

约束。

在应用where T:class约束时,避免对类型参数使用==和!=运

算符,因为这些运算符仅测试引用同一性而不测试值相等性。即使在

用作参数的类型中重载这些运算符也是如此。下面的代码说明了这一

点;即使String类重载==运算符,输出也为false。

public static void OpTest(T s,T t)where T:class

{

System.Console.WriteLine(s==t);

}

static void Main()

{

string s1="foo";

System.Text.StringBuilder sb=new System.Text.StringBuilder("foo"); string s2=sb.ToString();

OpTest(s1,s2);//输出false

}

这种情况的原因在于,编译器在编译时只知道T是引用类型,因此

必须使用对所有引用类型都有效的默认运算符。如果必须测试值相等

性,建议的方法是同时应用where T:IComparable约束,并

在将用于构造泛型类的任何类中实现该接口。

可以对多个参数应用约束,并对一个参数应用多个约束,如下面的示

例所示:

class Base{}

class Test

where U:

struct

where T:Base,new(){}

没有约束的类型参数(如公共类SampleClass{}中的T)称为

未绑定的类型参数。未绑定的类型参数具有以下规则:

不能使用!=和==运算符,因为无法保证具体类型参数能支持这

些运算符。

可以在它们与System.Object之间来回转换,或将它们显式转换为

任何接口类型。

可以将它们与null进行比较。将未绑定的参数与null进行比较时,如果类型参数为值类型,则该比较将始终返回false。

用作约束的泛型类型参数称为裸类型约束。当具有自己的类型参数的成员函数必须将该参数约束为包含类型的类型参数时,裸类型约束很有用,如下面的示例所示:

class List

{

void Add(Listitems)where U:T{/*...*/}

}

在上面的示例中,T在Add方法的上下文中是一个裸类型约束,而

在List类的上下文中是一个未绑定的类型参数。

裸类型约束还可以在泛型类定义中使用。注意,还必须已经和其他任

何类型参数一起在尖括号中声明了裸类型约束:

//naked type constraint

public class SampleClasswhere T:V{}

泛型类的裸类型约束的作用非常有限,因为编译器除了假设某个裸类型约束派生自System.Object以外,不会做其他任何假设。在希望强制两个类型参数之间的继承关系的情况下,可对泛型类使用裸类型约束。

使用泛型集合类

泛型最常见的用途是泛型集合,从.NET2.0版类库开始提供一个新

的命名空间Sysstem.Collection.Generic,其中包含了几个新

的基于泛型的集合类。使用泛型集合类可以提供更高的类型安全性,在某些情况下还可以提供更好的性能,尤其是在存储值类型时,这种优势更明显。

常用的非泛型集合类及其对应的泛型集合类

如下几种泛型集合类型没有对应的非泛型类型:

LinkedList是一个通用的链接链表,它提供运算复杂为O(1)的插入和

移除操作。

SortedDictionary是一个排序的字典,其插入和检索操作的运算复杂度

为O(log n),这使它成为SortedList的十分有用的替代类型。

KeyedCollection是介于列表和字典之间的混合类型,它提供了一种存

储包含自己健的对象的方法。

一般情况下,建议使用泛型集合,因为这样可以获得类型安全的好处而

不需要从集合类型派生并实现特定的成员。此外如果集合元素为值类

型,

泛型集合类型的性能通常优于对应的非泛型集合类型(并优于从非泛型

集合类型派生的类型),因为使用泛型时不必对元素进行装箱。

对应的非泛型集合和泛型集合的功能一般基本相同,但是一些泛型类型

具有在非泛型集合类型中没用的功能。例如,List类(对应用非泛型ArrayList类)具有许多接受泛型委托(如允许指定搜索列表的方法的Predicate委托、表示操作每个列表元素的Action委托和允许定义类型

之间转换的Converter委托)的方法。List类允许指定自己的用于

排序和搜索列表的IComparer泛型接口实现。

下面看下List和Dictionary的程式代码:

using System;

using System.Collections.Generic;

namespace Generic_List

{

class Test

{

static void Main(string[]args)

{

Listli=new List();

//与ArrayList一样默认容量大小为0,我在前面的文章还提到过

实验十 泛型与集合框架

实验十泛型与集合框架 1.实验目的 1、掌握LinkedList类和Collections类提供的用于排序和查找链表中 的数据的方法 2、掌握用散列映射来存储数据 3、掌握TreeSet类的使用 2.实验内容 1、根据附录里的源代码,按照注释要求,完成代码填空,使程序能够运行 得出结果。 1)实验1 按身高排序 2)实验2 英汉小字典 3)实验3 演出节目单 4)实验4输出args[]中的单词 2、设计编写程序完成以下任务。 1)仿照实验1编写TV类,要求通过实现Comparable接口规定该类的对象的大小关系,按price值得大小确定大小关系,即电视机按其价格确定之间的大小关系。 2)从控制台输入若干个单词(输入回车结束)放入集合中,将这些单词排序后(忽略大小写)打印出来。 知识点:List接口的实现类、String常用方法 3)请使用LinkedList来模拟一个队列(先进先出的特性): (1)拥有放入对象的方法void put(Object o) (2)取出对象的方法Object get() (3)判断队列当中是否为空的方法boolean isEmpty();并且,编写测试代码,验证你的队列是否正确。 知识点:List接口的实现类LinkedList常用方法 4)在一个列表中存储以下元素:apple,grape,banana,pear (1)返回集合中的最大的和最小的元素 (2)将集合进行排序,并将排序后的结果打印在控制台上 知识点:Collections类中的方法 3.实验步骤 略 4.评分标准 1.A——内容功能完善,编程风格好,人机接口界面好; 2.B——内容功能完善,编程风格良好,人机接口界面良好;

JAVA实验报告-集合框架与泛型机制

Java 语言程序设计 C 实验报告 集合框架及泛型机制 学生姓名 专业、班级 指导教师 成绩 计算机与信息工程学院 年月日

一、实验目的 学习课程相关章节知识,通过上机练习,掌握以下知识: 1.掌握 List 接口下 ArrayList 及 LinkedList 的使用方法。 2.掌握 Map 接口下 HashMap 及 HashTable的使用方法 3.掌握集合中泛型的使用 二、实验内容 利用集合完成象数据库那样存储数据,并且可以简单查询,利用 map 存储学生信息,字段如下: id ,name,age,实现步骤: (1)创建类,类图如下: (2)在 main 方法编写逻辑代码 (3)运行程序并测试结果 package https://www.360docs.net/doc/424794218.html,; public class Student { private String name ; private int age ; private String id ;

public String getName() { return name ; } public void setName(String name ) { this . name =name ; } public int getAge() { return age ; } public void setAge(int age ) { this. age=age ; } public String getId() { return id; } public void setId(String id) { this. id=id; } public Student(String name ,int age , String id ) { super(); this. name =name ; this. age=age ; this. id=id; } public void sayHi() { System.out.println("name=" +this.getName()+"age=" + this .getAge()+" " + "id=" + this.getId()); } }

通过实例学习C#开发中的泛型

C#中所谓泛型:即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。 C#泛型赋予了代码更强的类型安全,更好的复用,更高的效率,更清晰的约束。 C#泛型机制简介 C#泛型能力由CLR在运行时支持,区别于C++的编译时模板机制,和java 的编译时的“搽拭法”。这使得泛型能力可以在各个支持CLR的语言之间进行无缝的互操作。 C#泛型代码在被编译为IL和元数据时,采用特殊的占位符来表示泛型类型,并用专有的IL指令支持泛型操作。而真正的泛型实例化工作以“on-demand”的方式,发生在JIT编译时。 C#泛型编译机制 第一轮编译时,编译器只为Stack类型产生“泛型版”的IL代码和元数据,并不进行泛型类型的实例化,T在中间只充当占位符。 JIT编译时,当JIT编译器第一次遇到Stack时,将用int类型替换“泛型版”IL代码与元数据中的T -- 进行泛型类型的实例化。 CLR为所有类型参数为“引用类型”的泛型类型产生同一份代码,但如果类型参数为“值类型”,对每一个不同的“值类型”,CLR将为其产生一份独立的代码。 C#泛型的几个特点 如果实例化泛型类型的参数相同,那么JIT编译器会重复使用该类型,因此C#的动态泛型能力避免了C++静态模板可能导致的代码膨胀的问题。 C#泛型类型携带有丰富的元数据,因此C#的泛型类型可以应用于强大的反射技术。 C#的泛型采用“基类、接口、构造器、值类型/引用类型”的约束方式来实现对类型参数的“显示约束”,提高了类型安全的同时,也丧失了C++模板基于“签名”的隐式约束所具有的高灵活性。 C#泛型类与结构 class C{} //合法 class D:C{} //合法

实验11泛型与集合

实验内容: (1)定义一个泛型类In strume nt,其中包括一个泛型方法void play(E x) 定义两种乐器类:Cello、Violin可以进行演奏。定义一个测试类进行测试。 package ex111; public class Violin { public String toStri ng() { System.out.println("violin ....... "); return ""; } } package ex111; public class Test_Ma in { public static void main( Stri ng[] args) { instrumentmodel = new instrument(); in strume ntvVioli n> model1 = new in strume ntvVioli n>(); Cello cello = new Cello(); Violin violin = new Violi n(); model.play(cello); model1.play(violi n); } } package ex111; class in strume nt {//泛型类void play(E x) { x.toStri ng(); } } package ex111; public class Cello { public Stri ng toStri ng(){ System.out.println("cello ....... "); return ""; } } (2)输入10个数字保存到List中,并按倒序显示出来 package ex112; import java.util.ArrayList; import java.util.Collectio ns; import java.util.List; import java.util.Sca nner; public class Test{ public static void main(final String[] args) { final List< In teger> in tegers = new ArrayListvl nteger>(); final Scanner sca nner = new Scann er(System.i n); for (int i = 1; i <= 3; i++) {

第8章_泛型编程习题_参考答案

《面向对象程序设计》习题 第8章泛型编程 一、选择题(共40分,每题2分) 二、填空题(共20分,每空2分) 1. 逻辑数据类型 2. 函数类 3. 函数模板类模板 4.函数类型形参类型 5.2 6. 尖括号 三、下列程序有2个错,找出并修改(共6分) 错1:public: A(T a, b) // A(T a,T b) {x=a,y=b;s=x+y;} 错2: int main() { A add(10,100); // A add(10,100); add.show(); return 0; } 四、看程序写结果(共12分,每题4分) 1. 2. 3.

五、编程题(22分) 1.设计一个函数模板,实现两数的交换,并用int、float、double、char类型的数据进行测试。 #include #include using namespace std; template void change(T &x, T &y) { T temp; temp=x; x=y; y=temp; } int main() { int a=12, b=34; float c=1.1, d=2.2; double e=1.23456789, f=2.23456789; char u='A', v='B'; cout<<"交换前:a="< 19/// 20public T this[int index] 21 { 22get 23 { 24if (index >= arr.Length) 25 { 26throw new System.Exception("数组下标越界 "); 27 } 28else

29 { 30return arr[index]; 31 } 32 } 33set 34 { 35if (index >= arr.Length) 36 { 37throw new System.Exception("数组下标越界 "); 38 } 39else 40 { 41 arr[index]=value; 42 } 43 } 44 } 45 } 调用: 1protected void Page_Load(object sender, EventArgs e) 2 { 3 MyList list = new MyList(4); 4 5 list.Add(1); 6 list.Add(4); 7 list.Add(5); 8 list.Add(6); 9for (int i = 0; i < list.count; i++) 10 { 11 Response.Write(list[i].ToString()); 12 } 13 } 注意: 1、是在运行时,将堆空间里的对象内部所有的占位符都替换成传入的类型. 2、泛型是指带类型参数的类,而不是类型参数本身。

实验11泛型与集合

实验内容: (1) 定义一个泛型类Instrument<E 〉,其中包括一个泛型方法void pla y(E x)。 定义两种乐器类:Cello、Violin 可以进行演奏。定义一个测试类进行测试. package ex111; public class Violin{ publicString toString() { System、out、println("violin、、、、、、、、、"); return ””; } } package ex111; public class Test_Main{ public staticvoid main(String[]args){ instrument〈Cello>model = new instrument〈Cello〉(); instrument

实验七:Java集合与泛型

实验七Java集合与泛型 一、实验目的 1)掌握集合的概念、体系结构、分类及使用场景 2)了解Set接口及主要实现类(HashSet、TreeSet) 3)了解List接口及主要实现类(ArrayList、LinkedList、Vector) 4)掌握ArrayList的使用 5)掌握ArrayList与Vector的区别 6)了解Map接口及主要实现类(HashMap、TreeMap、HashTable) 7)掌握HashMap的使用 8)掌握HashMap与HashTable的区别 二、实验环境 JDK1.6+Eclpise3.2 三、实验准备 1)复习课件中理论知识 2)练习课堂所讲的例子 四、实验内容 1、编写程序练习List集合的基本使用: 1) 创建一个只能容纳String对象名为names的ArrayList集合; 2)按顺序往集合中添加5个字符串对象:“张三”、“李四”、“王五”、“马六”、“赵七”; 3)对集合进行遍历,分别打印集合中的每个元素的位置与内容; 4)首先打印集合的大小,然后删除集合中的第3个元素,并显示删除元素的内容,然后再打印目前集合中第3个元素的内容,并再次打印集合的大小。 2、编写程序练习Map集合的基本使用: 1)创建一个只能值只能容纳String对象的person的HashMap集合; 2)往集合中添加5个“键-值”对象:id—>”1”、name—>”张三”、sex—>”男”、age—>”25”、love—>”爱学Java” 3)对集合进行遍历,分别打印集合中的每个元素的键与值; 4)首先打印集合的大小,然后删除集合中的键为age的元素,并显示删除元素的内容,并再次打印集合的大小。 五、验过程及结果 第1题调试结果如下图:

C#泛型探究(自学篇)

前言 前几日同学告诉我他老师告诉他,泛型是定义一种通用的方法,至于为什么用泛型他的答 案还是定义一种通用的方法,当时我也没有学,还不懂啦,毕竟人家是计算机专业的科班生,我当 然没有发言权,只是怀疑的记下了这个错误的结论打算以后看看是不是对的,这两天算是把泛型学 了一下,其实它定义的不只是方法,自己感觉他就是一种规范代码执行效率的模版,这样极不容易 出错,并把我们常用的箱拆箱操作过程给省了,提高了编译器的执行效率,。至于为什么用泛型这 个我貌似已经说明白了,泛型多用于集合类操作,我在这里随意的拿出C#定义的ArrayList的 Add方法的定义我们一起看看: public virtual int Add( Object value ) 可以看出我们可以往ArrayList里添加任何类型的元素,假如有一个string类型的str字符 串它在添加到ArrayList lib的过程中实际进行了装箱操作,即object value=str;那么我 们在获取这个值得时候必须这样使用string s=(string)lib[0];不能遗漏(string)否则会提示你, 错误1无法将类型“object”隐式转换为“string”。存在一个显式转换(是否缺少强制转换?) 但是你假如这样写:int a=(int)lib[0];程序在运行前是无法报错的,只要一旦运行就会出 现异常,而这些错误都可以利用泛型轻松搞定,让你在编译时就可以发现错误,具体的就看你怎么 领悟了,我在文章里没有写任何定义的语法格式,因为这个既没必要说,这是常识,出来混这些迟 早是要明白的,呵呵。玩笑啦......欢迎新手同学来我的博客交流学习,我也希望你们可以为我敞 开心怀,因为我既不是计算机专业的学生,甚至上了大学我已经不再是理工类的学生。我无意扎进了 文科专业去叱咤风云啦,哎,这个文科专业名字太有点科学技术的味道了。我喜欢 ........ 我的博客地址是:https://www.360docs.net/doc/424794218.html,

c代码规范

c代码规范(总7页) -CAL-FENGHAI.-(YICAI)-Company One1 -CAL-本页仅作为文档封面,使用请直接删除

C# 代码规范 1、前言 本文档定义了一些通用的代码规范和准则,一般情况下本文档适用于项目组所有项目,特殊情况下,如果客户有自己的代码规范,以客户的代码优先。 2、大小写约定 2.1、大小写样式,本文中将出现两种大小写样式,这里先分别定义: Pascal大小写 将标识符的首字母和后面连接的每个单词的首字母都大写。可以对三字符或更多字符的标识符使用 Pascal 大小写。例如:BackColor Camel大小写 标识符的首字母小写,而每个后面连接的单词的首字母都大写。例如:backColor 匈牙利命名法 基本原则是:变量名=属性+类型+对象描述。例如:lblName 2.2、标识符大小写规则 2.2.1、下表中列出常见的代码元素的样式规范和示例 标识符规则示例 类Pascal AppDomain 枚举类型Pascal ErrorLevel 枚举值Pascal Warning 事件Pascal ValueChanging, ValueChanged 异常类Pascal WebException 只读的静态字段Pascal CurrentUser 接口Pascal IDisposable 方法Pascal ToString 命名空间Pascal 参数Camel typeName 属性Pascal Name 常量全大写MAXLENGTH, LENGTH_MAX Web或Win控件匈牙利txtName 2.2.2、除了遵循以上大小写约定外还需注意以下约定(除常量为特例): 如果标识符由多个单词组成,请不要在各单词之间使用分隔符,如下划线(“_”)或连字符(“-”)等。而应使用大小写来指示每个单词的开头。 所有公共的成员如:方法、属性,都应使用Pascal大小写样式 2.3、首缩写词的大小写规则 2.3.1、首字母缩写词 首字母缩写词是由术语或短语中各单词的首字母构成的单词。 例如,HTML 是 Hypertext Markup Language 的首字母缩写。为了方便编码规范的实施,本文规定受字母缩写词必须至少为两个单词,正好为两个单词的首字母缩写词称其为“短型首字母缩写词”,两个单词以上的称其为“长型首字母缩写词” 2.3.2、单缩写词

学号姓名--集合框架与泛型实验报告

浙江大学城市学院实验报告 课程名称面向对象程序设计 实验项目名称集合框架与泛型 学生姓名专业班级学号 一. 实验目的和要求 1. 了解Java集合框架的接口和实现类 2. 理解泛型类、泛型接口、泛型方法的特点 3. 掌握List接口及其实现类LinkedList、ArrayList 4. 了解Set接口及其实现类HashSet、TreeSet 5. 了解Map及其实现类HashMap、TreeMap 二. 实验内容 1. 分析Java集合框架的接口和实现类的组成 2. 分析泛型类、泛型接口、泛型方法的特点 3. 编程实现:设计学生管理类StudentManager(用List集合管理学生对象) 4. 选作-编程实现:设计学生管理类StudentManager(用Set集合管理学生对象) 5. 选作-编程实现:设计学生管理类StudentManager(用Map管理学生对象) 三. 实验结果与分析(可将程序运行结果截屏,也可分析运行结果) 1. 分析Java集合框架的接口和实现类的组成 请查阅书籍和Java帮助文档,说明Java集合框架的接口组成以及它们的继承关系,并针对每个接口给出具体的实现类。 答: 2. 分析泛型类、泛型接口、泛型方法的特点 请查阅书籍和Java帮助文档,举例说明泛型类、泛型接口、泛型方法的特点。 答: 3. 编程实现:设计学生管理类StudentManager(用List集合管理学生对象)。 StudentManager类的功能包括添加学生、查询学生、删除学生、统计学生成绩等。需要设计表示学生对象的Student类,并用LinkedList或ArrayList集合来管理可被数量的学生对象。另外还需要设计测试类Test来验证StudentManager的功能。 4. 编程实现:设计学生管理类StudentManager(用Set集合管理学生对象)。具体功能 要求同第3题,但是需要用Set的实现类(比如HashSet、TreeSet)管理学生对象。

【个人总结系列-47】C C++编程注意问题总结-模板和泛型编程-结构体注意-中文字符读取-产生随机数

C/C++编程注意问题总结-模板和泛型编程-结构体注意-中文字符读 取-产生随机数 1.1.1 C++模板和泛型编程总结 ?函数模板:函数中有不确定的类型T(或成为模板类型) template T1 fun(T2 n) 函数模板在调用时自动根据参数的类型判断产生哪种类型的实例。所以程序员必须自己保证在函数中的类型T能够胜任所参与的运算。比如在函数fun()中有T类型的两个数据进行+运算,则程序员必须保证参数能够进行+运算。 ?类模板 类模板:类中有不确定的类型T(或成为模板类型) template class Person{} 类中函数在类外部的实现:必须在每个函数上面加一个template,以及在类后面用<>说明类中用到的模板类型T,如下所示: template Person::int getAge(){} 类模板在实例化时(声明和new一个类模板时),必须用<具体的T>注明类的类型。 凡是实例化一个类模板时(即用这种类时),必须要注明具体的类型。如: Person p; new的时候 Person p = new Person("Jim",20); 1.1.2 结构体需要注意的问题 ?结构指针 结构指针:struct string *student; 实际上, student->name就是(*student).name的缩写形式。 需要指出的是结构指针是指向结构的一个指针, 即结构中第一个成员的首地址,因此 在使用之前应该对结构指针初始化,即分配整个结构长度的字节空间, 这可用下面函数完成, 仍以上例来说明如下: student=(struct string*)malloc(sizeof (struct string)); 结构变量struct string student1,访问时https://www.360docs.net/doc/424794218.html,; 结构变量指针struct string *student2,访问时student2->name;或 (*student2).name ?结构体的创建和初始化 New与malloc一个结构体: Struct string *student=(struct string*)malloc(sizeof (struct string)); Struct string *student = new string;

实验五 集合类与泛型

实验五集合类与泛型 1.实验目的 (1)掌握ArrayList类与LinkedList类的用法; (2)掌握TreeSet类的用法; (3)掌握Map接口及其实现类的用法 (4)掌握泛型的用法。 2.实验内容 实验题1 有四个类,主类Store在包https://www.360docs.net/doc/424794218.html,.nwsuaf.jp.p4中,Mobile、Mp3Player、Product在包https://www.360docs.net/doc/424794218.html,.nwsuaf.jp.p4.data中,Mobile、Mp3Player是Product的子类, Product类实现Comparable接口,重写了Comparable接口中方法compareTo,实现了product对象按照价格排序。 基本要求: (1)在主类Store中实例化多个Mobile类与Mp3Player的实例,分别将这些实例用ArrayList与LinkedList存放,最后用StringBuiler存放并将其输出。 (2)用迭代器(iterator)将实例对象输出(要求用加强型for循环)。 Store类 package https://www.360docs.net/doc/424794218.html,.nwsuaf.jp.p44; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javax.swing.JOptionPane;

import https://www.360docs.net/doc/424794218.html,.nwsuaf.jp.p4.data.Mobile; import https://www.360docs.net/doc/424794218.html,.nwsuaf.jp.p4.data.Mp3Player; import https://www.360docs.net/doc/424794218.html,.nwsuaf.jp.p4.data.Product; public class Store { public static int count=0; public static void main(String[] args) { Mobile m1=new Mobile("E365 on china Mobile",1780); Mobile m2=new Mobile("E3330 on china Mobile",1450); Mp3Player mp1=new Mp3Player("Meiz0 X3 (256MB)",399); Mp3Player mp2=new Mp3Player("Meiz0 E5 (512MB)",580); Mp3Player mp3=new Mp3Player("Xlive XM Mp3Player(256MB)",930); Product p[]={mp2,mp1,mp3,m1,m2}; Arrays.sort(p); StringBuilder text=new StringBuilder(); for(Product i:p){ text.append(i).append("\n"); } System.out.println("用StringBuiler输出:\n"+text); List list1=new ArrayList();//用到泛型因为Product是mp3和mobil的总类,ArrayList只能放一种类型 List list2=new LinkedList(); for(int i=0;i

java中的泛型

Java中的泛型 JDK1.5令我们期待很久,可是当他发布的时候却更换版本号为5.0。这说明Java已经有大幅度的变化。本文将讲解JDK5.0支持的新功能-----Java的泛型. 1、Java泛型 其实Java的泛型就是创建一个用类型作为参数的类。就象我们写类的方法一样,方法是这样的method(String str1,String str2 ),方法中参数str1、str2的值是可变的。而泛型也是一样的,这样写class Java_Generics<K,V>,这里边的K和V就象方法中的参数str1和str2,也是可变。下面看看例子: 正确输出:value 这只是个例子(Java中集合框架都泛型化了,这里费了2遍事.),不过看看是不是创建一个用类型作为参数的类,参数是K,V,传入的“值”是String类型。这个类他没有特定的待处理型别,以前我们定义好了一个类,在输入输入参数有所固定,是什么型别的有要求,但是现在编写程序,完全可以不制定参数的类型,具体用的时候来确定,增加了程序的通用性,像是一个模板。 呵呵,类似C++的模板(类似)。 1.1. 泛型通配符 下面我们先看看这些程序:

看看这个方法有没有异议,这个方法会通过编译的,假如你传入String,就是这样List <String>。 接着我们调用它,问题就出现了,我们将一个List<String>当作List传给了方法,JVM会给我们一个警告,说这个破坏了类型安全,因为从List中返回的都是Object类型的,而让我们再看看下面的方法。 因为这里的List<String>不是List<Object>的子类,不是String与Object的关系,就是说List<String>不隶属于list<Object>,他们不是继承关系,所以是不行的,这里的extends是表示限制的。 类型通配符是很神奇的,List<?>这个你能为他做什么呢?怎么都是“?”,它似乎不确定,他总不能返回一个?作为类型的数据吧,是啊他是不会返回一个“?”来问程序员的?JVM会做简单的思考的,看看代码吧,更直观些。 这段代码没问题的,l1.get(0)将返回一个Object。 1.2. 编写泛型类要注意: 1) 在定义一个泛型类的时候,在“<>”之间定义形式类型参数,例如:“class TestGen <K,V>”,其中“K” , “V”不代表值,而是表示类型。 2) 实例化泛型对象的时候,一定要在类名后面指定类型参数的值(类型),一共要有两次书写。例如: TestGen<String,String> t=new TestGen<String,String>();

实验七 C#泛型

实验七泛型 实验学时:2学时 实验类型:验证 实验要求:必做 一、实验目的 1.掌握泛型的基本使用; 2.声明和使用泛型方法 二、实验内容 实验1使用泛型List创建各种类型的列表 实验要求:参照课本例11.2,使用泛型List创建并显示整型数组列表ArrayList1:1,3,5;字符串型数组列表ArrayList2:”One”,”Two”,”Three”。 源程序: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace fanxing { class Program { static void Main(string[] args) { List list1 = new List(); list1.Add(1); list1.Add(3); list1.Add(5); Console.WriteLine("整数数组列表ArrayList1的内容如下:"); foreach (int x in list1) { Console.WriteLine(x); } List list2 = new List(); list2.Add("One"); list2.Add("Two"); list2.Add("Three"); 1

Console.WriteLine("字符串型数组列表ArrayList2的内容如下:"); foreach (string s in list2) { Console.WriteLine(s); } Console.ReadLine(); } } } 运行结果: 实验2 声明和使用泛型方法 实验要求:参照课本例11.5,声明泛型方法Swap,实现两个数内容的交换。在main ()中输入任意两个整数和任意两个实数,分别调用泛型方法Swap,实现整数内容的交换和实数内容的交换。 源程序: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace fanxingfangfa { class Program { static void Swap(ref T lhs, ref T rhs) { T temp; temp = lhs; lhs = rhs; rhs = temp; } static void Main(string[] args) { Console.WriteLine("请输入任意两个整数:"); int a, b; String s = Console.ReadLine(); a = int.Parse(s); s = Console.ReadLine();

新泛型)

基于泛型DAO的spring和hibernate的集成(转) 编写Spring+Hibernate框架下的应用,总是离不了编写一个通用的泛型GenericHibernateDao。查阅了网上不少的GenericHibernateDao实现,归纳整理为如下实现,供后续编码参考。 首先定义接口泛型DAO接口GenericDao package com.th.huz; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.hibernate.Criteria; import org.hibernate.LockMode; import org.hibernate.criterion.DetachedCriteria; public interface GenericDao { // -------------------- 基本检索、增加、修改、删除操作-------------------- // 根据主键获取实体。如果没有相应的实体,返回null。 public T get(PK id); // 根据主键获取实体并加锁。如果没有相应的实体,返回null。 public T getWithLock(PK id, LockMode lock); // 根据主键获取实体。如果没有相应的实体,抛出异常。 public T load(PK id); // 根据主键获取实体并加锁。如果没有相应的实体,抛出异常。 public T loadWithLock(PK id, LockMode lock); // 获取全部实体。 public List loadAll(); // loadAllWithLock() ? // 更新实体 public void update(T entity); // 更新实体并加锁 public void updateWithLock(T entity, LockMode lock); // 存储实体到数据库

C++模板函数与Java泛型

C++模板函数 #include "iostream" using namespace std; intint_ab(inta,int b) { returna+a*b; } doubledouble_ab(double a,double b) { returna+a*b; } int main(){ cout<或者template来定义一个任意类型的数据T,定义后的函数必须紧跟着。 #include "iostream" using namespace std; template T1 ab(T1 a,T1 b) { returna+a*b; } int main(){ cout< T1 ab(T1 a,T1 b)

8. Java基础_泛型

泛型 1. 介绍 下面是那种典型用法: List myIntList = new ArrayList();// 1 myIntList.add(new Integer(0));// 2 Integer x = (Integer) myIntList.iterator().next();// 3 第3 行的类型转换有些烦人。通常情况下,程序员知道一个特定的list 里边放的是什么类型的数据。但是,这个类型转换是必须的(essential)。编 译器只能保证iterator 返回的是Object 类型。为了保证对Integer 类型变量赋值的类型安全,必须进行类型转换。 当然,这个类型转换不仅仅带来了混乱,它还可能产生一个运行时错误(run time error),因为程序员可能会犯错。 程序员如何才能明确表示他们的意图,把一个list(集合) 中的内容限制 为一个特定的数据类型呢?这就是generics 背后的核心思想。这是上面程序片断的一个泛型版本: List myIntList = new ArrayList(); // 1 myIntList.add(new Integer(0)); // 2 Integer x = myIntList.iterator().next(); // 3 注意变量myIntList 的类型声明。它指定这不是一个任意的List,而是 一个Integer 的List,写作:List。我们说List 是一个带一个类型参数的泛型接口(a generic interface that takes a type parameter),本 例中,类型参数是Integer。我们在创建这个List 对象的时候也指定了一个类型参数。 另一个需要注意的是第 3 行没了类型转换。 现在,你可能认为我们已经成功地去掉了程序里的混乱。我们用第1 行的类型参数取代了第 3 行的类型转换。然而,这里还有个很大的不同。编译器现在能够在编译时检查程序的正确性。当我们说myIntList 被声明为List类型,这告诉我们无论何时何地使用myIntList 变量,编译器保证其中的元素的正确的类型。 实际结果是,这可以增加可读性和稳定性(robustness),尤其在大型的 程序中。 2. 定义简单的泛型 下面是从java.util包中的List接口和Iterator 接口的定义中摘录的片断:public interface List { void add(E x); Iterator iterator(); } public interface Iterator {

Java泛型实现单链表

学号11710115 天津城建大学 Java 语言程序设计C 实验报告 实验3:泛型实现链表 学生姓名路江飞 班级11卓越七班

一、实验内容 1.掌握使用Java语言进行结构化程序设计; 2.熟悉Java泛型。 3.熟悉Eclipse开发环境,编写简单的Application程序,并编译和执行。 二、实验要求 1.调试程序、编译,运行后得到正确的结果; 2.写出实验报告,要求记录编译和执行Java程序当中的系统错误信息提示,并给出解决办法。 三、实验结果 文件1: package _List; class Node{ E e; Node next; Node(E e){ this.e=e; next=null; } } 文件2: package _List; public class Show { void print(){ System.out.println("*************************************"); System.out.println("* 1.按位查找*"); System.out.println("* 2.按值查找*"); System.out.println("* 3.插入*"); System.out.println("* 4.按位删除*"); System.out.println("* 5.按值删除*"); System.out.println("* 6.修改*"); System.out.println("* 7.遍历*");

System.out.println("* 8.查看链表长度*"); System.out.println("* 9.退出*"); System.out.println("*************************************"); } } 文件3: package _List; import java.util.Scanner; public class List { Node head; List(){ this.head=null; } List(E e[],int n){ //构造函数 this.head=new Node (e[0]); Node r=this.head; for(int i=1;is=new Node (e[i]); r.next=s; r=s; } r.next=null; } void add (E e){//按位置插入 int index,b=1; Scanner input=new Scanner(System.in); for(int j=0;b==1;j++){ System.out.print("请输入插入的位置(第一个数据之前是0号位置,以此类推):");