泛型

来源:互联网 发布:c语言continue和break 编辑:程序博客网 时间:2024/05/21 22:56
1. 含义:泛型是指有一个或者多个类型占位符的类,结构体,接口,方法。类型可以用作参数,实例化或者声明变量,返回值。
2. 使用:简单的来说:当多个方法或者类,结构体,接口功能相同,只是类型不一样时,就可以用泛型类或方法。泛型类或方法是为了减少代码。还有一种可以减少代码的方法是Object。
2者都可以在写代码的时候不用在意它是什么类型,泛型是在运行时才加以区分,object是在使用这个变量时才区分。但是二者还是有区别。
a. Object:当用object时,可能涉及到性能和运行时代码异常的情况。当类型是值类型的时候,会存在装箱和拆箱的情况(也就是强制转换),这样会造成性能的损耗。
 比如Array类,他可以存储任何类型的数据。当时用的时候,如果存入int类型的数据,就可能会出现装箱和拆箱。如果一不小心存入不能转换成为int的数据后,
 在使用时,就会出现异常。
b. 泛型。不会存在上面的地方。通俗的说,泛型就是给了一个占位符,当运行时,用你传递类型替换掉占位符。
  但是类型不同,方式也不同。当类型是值类型时,会生成一个另外一个类。这是因为值 类型不同所占用的内存空间不同,所以会产生另外一个类。
  引用类型值不会,只会产生一个引用地址。
3. 定义:模拟了一个集合
class MyList<T>
{
private int count;
private T[] arr;
private int nCurrent;

public int Count
{
get{
return count;
}
}

public MyList() : this(4)
{

}

public MyList(int nCount)
{
if (nCount <= 0)
nCount = 4;
count = nCount;
arr = new T[nCount];
}

public void Add(T obj)
{
arr[nCurrent] = obj;
nCurrent++;
}

public T this[int nIndex]
{
get
{
if (nIndex >= 0 && nIndex < count)
{
return arr[nIndex];
}
return arr[0];
}
set
{
if (nIndex >= 0 && nIndex < count)
{
arr[nIndex] = value;
}
}
}
}
使用:MyList<int> lstInt = new MyList<int>();  // 第一次会重新生成一个类  泛型的生成时的类.MyList`1[System.Int32]
              MyList<float> lstFloat = new MyList<float>(); // 第一次会重新生成一个类  泛型的生成时的类.MyList`1[System.Int32]
              MyList<C1> lstC1 = new MyList<C1>(); // 第一次会重新生成一个类  泛型的生成时的类.MyList`1[泛型的生成时的类.C1]     PS: 书中说的是不会产生新的类,但是还是产生了。也许是类还是同一个类,只是把T替换成了C1,不明白
              MyList<C2> lstC2 = new MyList<C2>(); // 第一次会重新生成一个类  泛型的生成时的类.MyList`1[泛型的生成时的类.C2]
 
方法差不多
public void MyFn<T>(T obj)
{
Console.Write(obj);
}
// 使用
MyFn<int>(3);
4. 一些功能和注意;
a. 默认值:T t = default(T); // 当有时候需要给其赋值,这时会给值类型赋0,引用类型为null
b. 约束:where T : struct T必须是值类型
where T : class T必须是引用类型
where T : 接口名 T必须实现某个接口
where T : 类名 T必须派生自某个类
where T : new() T类型必须有个无参的构造函数,目前没有有参的约束
where T : T2 T必须派生自泛型类型T2(裸类型约束)
多个条件:where T : class, new(),T2
c. 继承:class MyList<T> : MyBase<T>
{
}
d. 静态成员:静态成员必须是在同一个类型下的才能共享。
MyList<int>.Count 不等于 MyList<float>.Count
e. 泛型接口:和类一样
d. 协变和抗变:协变是指  参数类型,比如方法的参数可以接收该类型的任何子类
  抗变是指  返回类型,比如方法的返回值不能赋给该类型的任何子类的变量。 说白了就是多态(里氏替换原则)。
e. 泛型接口的协变和抗变:协变:interface IMyInterface<out T>  这样后,这个接口中T就只能是返回类型,不能当做参数
抗变:interface IMyInterface<in T>  这样后,这个T只能用作参数,不能用为返回类型
d. 方法的重写:在子类中重写父类的泛型方法时,是不需要再写父类方法的泛型约束,子类会自动从父类方法中继承。而且子类中的泛型方法的类型占位符可以和父类的不一样。
class Father
{
public virtual void SayHi<T, J>() where T : new()
{
T t = new T();
Console.Write("这是父类的方法" + t.ToString());
}
}

class Children : Father
{
public override void SayHi<K, I>()
{
K t = new K();
Console.Write("这是子类的方法" + t.ToString());
}
}
0 0
原创粉丝点击