1.泛型的概念
C#中的泛型与C++中的模板类似,泛型是实例化过程中提供的类型或类建立的。泛型并不限于类,还可以创建泛型接口、泛型方法,甚至泛型委托。这将极大提高代码的灵活性,正确使用泛型可以显著缩短开发时间。与C++不同的是,C#中所有操作都是在运行期间进行的。
2.使用泛型
- 可空类型
值类型必须包含一个值,它们可以在声明之后,赋值之前,在未赋值状态下存在,但不能以任何方式使用,而引用类型可以为null。有时让值类型为空是很有用的,泛型提供了使用System.Nullable
private Nullable
则可以为_nullableInt赋为null,如下:
_nullableInt = null;
可空类型非常有用,以致于C#中加入了语法:
int? _nullableIntSecond;
- System.Collections.Generic 名称空间
这个名称空间用于处理集合的泛型类型,使用的非常频繁。将以List
1.List
List
List
将创建T为String的List集合。
可以在代码中去查看List
2.对泛型列表进行排序和搜索
对泛型列表进行排序和搜索与和其它列表进行排序和搜索是一样的,如下为实例代码:
public class NumberCollection : List<int> { public NumberCollection(IEnumerable<int> initialNums) { foreach (var num in initialNums) { Add(num); } } public NumberCollection() { for (int i=0;i < 10;++i) { Add(i); } } public void Print() { foreach (var num in this) { Console.WriteLine(num); } Console.Read(); } }
public static class NumberCollectionDelegate { public static int Compare(int i,int j) { if (i > j) { return -1; } else if (i < j) { return 1; } return 0; } public static bool Find(int i) { if (i %2 == 0) { return true; } return false; }
public static Comparison
public static Predicate
}
var numColleciton = new NumberCollection(); numColleciton.Print(); numColleciton.Sort(NumberCollectionDelegate.CopmareDelegate); numColleciton.Print(); var newNumCollection = new NumberCollection(numColleciton.FindAll(NumberCollectionDelegate.Predicate)); newNumCollection.Print(); Console.ReadLine();
如上代码,首先定义了NumberCollection继承自List
numColleciton.Sort(NumberCollectionDelegate.Compare);
var newNumCollection = new NumberCollection(numColleciton.FindAll(NumberCollectionDelegate.Find));
这样就不需要显示引用Comparison
3.Dictionary
这个类型可以定义键值对的集合,这个类型需要实例化两个类型,分别用于键和值,以表示集合中的各个项。可以使用强类型化的Add方法添加键值对,如下。
Dictionary
stringIntDictionary.Add("Tom", 1);
stringIntDictionary.Add("Lucy", 2);
stringIntDictionary.Add("Lily", 3);
可以直接访问Dicitionary中的keys和Values属性值:
foreach (var key in stringIntDictionary.Keys)
{
Console.WriteLine(key);
}
foreach (var value in stringIntDictionary.Values)
{
Console.WriteLine(value);
}
同样可以迭代集合中每一项,如下:
foreach (KeyValuePair
{
Console.WriteLine("{0} = {1}", item.Key, item.Value);
}
对于Dictionary
3.定义泛型
1.定义泛型类
要创建泛型类,只需在类定义中包括尖括号:
class MyGenericClass
{
}
其中T可以是任意标识符,只需要遵循C#命名规则即可,但一般只使用T。
泛型类可以在其定义中包含任意多个类型,它们用逗号分开,例如:
class MyGenericClass
{
}
定义了这些类型之后,就可以在类定义中像使用其它类型那样使用它们,如下
class MyGenericClass{ private T1 _object; public MyGenericClass(T1 item) { _object = item; } public T1 InnerT1Object { get { return _object; } } }
注意不能假定使用了什么类型,例如:
_object = new T1();
因为此刻不知道T1是什么,也就不能使用它的构造函数,可能T1就没有构造函数,或者没有可公共访问的构造函数。因此要对泛型进行实际的操作需要更多了解其使用的类型。
- default关键字
要确定用于创建泛型类型的实例,需要了解一个最基本的情况,它是引用类型还是值类型,若不了解这个情况就不能直接对变量赋予null值。此时default关键字就派上了用场:
_object = default(T1);
如果_object是引用类型就给引用类型赋为null值,如果为值类型就给它赋为默认值。对于数字类型默认值为0,对于结构,按照相同的规则对它们进行赋值。default关键字允许对必须使用的类型进行更多的操作,为了进行更多的操作,必须对使用的类型进行更多的约束。
- 约束类型
前面使用的类型称为无绑定类型,因为没有对它们进行任何约束,而通过约束可以限定用于泛型的类型。在类定义中,可以使用where关键字,来限定用于泛型的类型,如下:
class MyGenericClass
其中constraint定义了约束,可以用这种能方式定义很多约束,每个约束之间用逗号分开。还可以使用多个where语句,定义泛型类型需要的任意类型或所有类型上的约束,约束必须出现在类型说明符的后面。
- 从泛型类中继承
类可以从泛型中继承,如
class Farm
{
}
如上代码Farm
首先,如果某个类型所继承的基类型中受到了约束,该类型就不能接触约束,即类型T在基类中使用时所受到的约束,必须扩展到子类中,至少于基类的约束相同。
- 泛型运算符
泛型类也支持运算符的重写。
- 泛型结构
结构与类相同,只是有一些细微的差别,而且结构是值类型,不是引用类型,所以可以创建泛型结构,如:
struct MyGenericStruct
{
}
2.定义泛型接口
定义泛型接口于定义泛型类所用的技术相同,例如:
interface IGenericwhere T : Object { void Sum(T x, T y); }
3.定义泛型方法
可以使用泛型方法以达到泛型方法的更一般形式,在泛型方法中,参数类型或返回类型由泛型类型参数所决定。
,例如:
T GetDefault() { return default(T); }
可以使用非泛型类,实现泛型方法:
public class Defaulter { public T GetDefault() { return default(T); } }
如果类是泛型的,那么需要为类中的泛型方法提供不同的标示符。如下代码会提示泛型方法:
public class Defaulter{ public T GetDefault () { return default(T); } }
会提示内部泛型参数与外部泛型参数相同,此时应该更改泛型标示符。
本篇内容参考C#入门经典。