NET基础之自定义泛型,泛型的多种应用

本篇文章主要介绍泛型的应用。

在.NET中泛型使用非常频繁,在控制台应用程序中,默认的引入了System.Collection.Generics名称空间,其中就提供了我们经常使用的泛型:List<T>和Dictionary<T>,相信用过它们的都知道它们的强大。还有一种我们经常使用的简单的泛型:System.Nullable<T>,即可空类型。我们可以:

泛型是.NET Framework 2.0
版类库就已经提供的语法,主要用于提高代码的可重用性、类型安全性和效率。

System.Nullable<int> nullableInt;

泛型的定义

声明一个可空的int类型,由于C#语法对这个做了简化通常我们都不这样写,而是这样写:

下面定义了一个普通类和一个泛型类,我们可以明确看到泛型类和普通类最大的区别就是多了一个<T>。

int? nullableInt

所以,这个<T>就标记了,这个类是泛型类。其中这个T,也可以写成A,B,C,D或其他字符。

下面重点介绍一下如何自定义泛型。

public class Generic
{
    public String Name;
}

public class Generic<T>
{
    public T Name;
}

 

泛型,顾名思义,就是泛指的类型。好比男人,女人,白人,黑人,可以泛称为【人】。

定义泛型类

但类型只能是一个类型。 那么泛型和类型之间是什么关系呢?

创建泛型类是需要在类定义中用尖括号语法:

其实很简单,泛型在定义的时候,是泛指类型;在使用的时候,就需要被指定,到底使用哪个类型。

class MyGenericClass<T>
{
    ...
}

即,使用时,就不在是泛指类型,而是特定类型。

T可以是任意的标示符,只要遵守命名规则即可。

好比,定义时,定义了一个人。但在使用时,必须明确指定,到底是黑人还是白人。

 

泛型的使用

可以把类型用在类成员的返回类型,方法参数类型等,例如:

泛型类跟普通类的使用方式一样,都需要实例化对象,再由对象来调用内部的属性或方法。

class MyGenericClass<T1, T2, T3>
{
    private T1 t1Object;

    public MyGenericClass(T1 item)
    {
        t1Object = item;
    }

    public T1 T1Object
    {
        get
        {
            return t1Object;
        }
    }
}

下面代码实例化了泛型Generic,实例化时,还指定了该泛型Generic的指定类型为String。

注意如果不能假定提供了什么类型。下面的代码不能执行:

所以要给泛型Generic的属性Name赋值,就需要赋值字符串类型的值。

class MyGenericClass<T1, T2, T3>
{
    private T1 t1Object;

    public MyGenericClass()
    {
        t1Object = new T1();
    }
}
public static void Excute()
{
    Generic<String> gs = new Generic<String>();
    gs.Name = "Kiba518";
}

因为我们不知道T1是否有公有的默认构造函数。

下面代码定义了一个Int类型的泛型Generic。

 

public static void Excute()
{
    Generic<int> gs = new Generic<int>();
    gs.Name = 518;
}

default关键字

泛型的默认值

如果我们定义了一个泛型的字段,我们想在构造函数中初始化它,但是我们不知道它的引用类型还是值类型,那么default就派上用处了:

泛型的默认值,如下面代码所示。需要使用default(T)来赋值。

public MyGenericClass()
{
    t1Object = default(T1);
}

不管泛型到底是String,int,bool或者是一个Class类型,都可以被自动赋值。

如果是值类型就赋值0,引用类型就赋值null。

public static void Excute()
{
    Generic<int> gs = new Generic<int>();
    gs.Name = 518;
    Generic<Task> gsTask = new Generic<Task>();
    gsTask.Name = new Task(()=> {
        Console.WriteLine("Kiba518");
    });
}

public class Generic<T>
{
    public T Name = default(T); 
}

 

泛型的约束

约束类型

在泛型类中,有个特别的约束可供我们使用。

在定义泛型的时候我们可以对类型进行约束,通过where关键字实现:

当我们不显示的声明时,这个约束不存在。但当我们显示的声明的时候,这个约束就会执行。

class MyGenericClass<T1> where T : constraint1,constraint
{
    ...
}

下面,我们来看看这个特别的约束。

constraint定义了约束,多个约束用逗号隔开,如果有多个类型:

public static void Excute()
{ 
    Generic<FanXing> gFanXing = new Generic<FanXing>();
    Generic<Base> gFanXingBase = new Generic<Base>();
    //Generic<string> gs = new Generic<string>(); 这样定义会报错
} 
public class Generic<T> where T : Base
{
    public T Name = default(T); 
} 
public class Base  
{
    public string Name { get; set; }
}
public class FanXing : Base
{
    public new string Name { get; set; }
}
class MyGenericClass<T1, T2> where T1 : constraint1 where T2 : constraint
{
    ...
}

如上面代码所示,【where T : Base】就是这个特别的约束。

下面给出一些可用的约束

当显示声明这个约束的时候,定义会限制泛型的类型。

                                       
约束                                                                 
说明

发表评论

电子邮件地址不会被公开。 必填项已用*标注