.NET基础之自定义泛型
system.nullable<int> nullableint;
声明一个可空的int类型,由于c#语法对这个做了简化通常我们都不这样写,而是这样写:
int? nullableint
下面重点介绍一下如何自定义泛型。
定义泛型类
创建泛型类是需要在类定义中用尖括号语法:
class mygenericclass<t>
{
...
}
t可以是任意的标示符,只要遵守命名规则即可。
可以把类型用在类成员的返回类型,方法参数类型等,例如:
复制代码
class mygenericclass<t1, t2, t3>
{
private t1 t1object;
public mygenericclass(t1 item)
{
t1object = item;
}
public t1 t1object
{
get
{
return t1object;
}
}
}
复制代码
注意如果不能假定提供了什么类型。下面的代码不能执行:
复制代码
class mygenericclass<t1, t2, t3>
{
private t1 t1object;
public mygenericclass()
{
t1object = new t1();
}
}
复制代码
因为我们不知道t1是否有公有的默认构造函数。
default关键字
如果我们定义了一个泛型的字段,我们想在构造函数中初始化它,但是我们不知道它的引用类型还是值类型,那么default就派上用处了:
public mygenericclass()
{
t1object = default(t1);
}
如果是值类型就赋值0,引用类型就赋值null。
约束类型
在定义泛型的时候我们可以对类型进行约束,通过where关键字实现:
class mygenericclass<t1> where t : constraint1,constraint
{
...
}
constraint定义了约束,多个约束用逗号隔开,如果有多个类型:
class mygenericclass<t1, t2> where t1 : constraint1 where t2 : constraint
{
...
}
下面给出一些可用的约束
约束 说明
where t:struct 使用结构约束,类型t必须是值类型
where t:calss 类约束指定,类型t必须是引用类型
where t:interface 指定类型t必须实现是接口或者实现了接口
where t:base-class 指定类型t必须是基类或者派生于基类
where t:new() 指定类型t必须有一个默认构造函数
下面结合以上知识给个实例:(ps不要看到代码多 其实很简单的 耐心看下去)
先定义四个类animal、cow 、chicken和supercow
复制代码
#region animal 虚基类 有一个name属性 feed方法和一个虚方法makeanoise
//虚基类 有一个name属性 feed方法和一个虚方法makeanoise
public abstract class animal
{
protected string name;
public string name
{
get
{
return name;
}
set
{
name = value;
}
}
public animal()
{
name = "the animal with no name";
}
public animal(string newname)
{
name = newname;
}
public void feed()
{
console.writeline("{0} has been fed.", name);
}
public abstract void makeanoise();
}
#endregion
复制代码
复制代码
//cow animal的子类,实现虚方法
public class cow:animal
{
public cow(string name) :
base(name)
{
}
public override void makeanoise()
{
console.writeline("{0} says 'moo!'", name);
}
}
复制代码
复制代码
//chicken类,animal子类
public class chicken:animal
{
public chicken(string name)
: base(name)
{ }
public override void makeanoise()
{
console.writeline("{0} says 'cluck'", name);
}
}
复制代码
复制代码
//cow的子类,有一个自己的方法fly
class supercow : cow
{
public supercow(string name) : base(name)
{
}
public void fly()
{
console.writeline("{0} is flying!", name);
}
public override void makeanoise()
{
console.writeline("{0} says 'i am supercow!'", name);
}
}
复制代码
类准备好了之后,我们可以开始定义我们的泛型了:
复制代码
//继承了迭代器接口,这样方便使用foreach 约束它的类型为animal及其子类
public class farm<t>:ienumerable<t> where t : animal
{
private list<t> animals = new list<t>();
public list<t> animals
{
get
{
return animals;
}
}
//迭代器
public ienumerator<t> getenumerator()
{
return animals.getenumerator();
}
ienumerator ienumerable.getenumerator()
{
return animals.getenumerator();
}
//执行所有animal的makeanoise()
public void makenoises()
{
foreach (t animal in animals)
{
animal.makeanoise();
}
}
//执行所有animal的feed()
public void feedtheanimals()
{
foreach (t animal in animals)
{
animal.feed();
}
}
//获得animals中的cow
public farm<cow> getcows()
{
farm<cow> cowfarm = new farm<cow>();
foreach (t animal in animals)
{
if (animal is cow)
{
cowfarm.animals.add(animal as cow);
}
}
return cowfarm;
}
}
复制代码
泛型定义好了,我们用写代码来调用它:
复制代码
class program
{
static void main(string[] args)
{
farm<animal> farm = new farm<animal>();
farm.animals.add(new cow("jack"));
farm.animals.add(new chicken("vera"));
farm.animals.add(new chicken("sally"));
farm.animals.add(new supercow("kevin"));
farm.makenoises();
farm<cow> dairyfarm = farm.getcows();
dairyfarm.feedtheanimals();
foreach (cow cow in dairyfarm)
{
if (cow is supercow)
{
(cow as supercow).fly();
}
}
console.readkey();
}
}