泛类学习
一.应用场景
1.效率.
2.易用,容错.
3.处理同一类事情.
二.应用.
1.无论在声明变量还是实例变量都要指定使用那个变量代替<T>
2.内部算法和数据操作保持不变
三.使用.
1.编译器不知道使用将要指定的具体类型
2.派生约束.,以逗号分割多个约束.
为使用的一般类型参数分别指定约束.以空格分割.
基类约束(最多一个).
可以同时约束一个基类以及一个或多个接口,但是该基类必须首先出现在派生约束列表中
代码
public class LinkedList where K : IComparable,IConvertible //多个约束以逗号分割
public class LinkedList where K : IComparable
where T : ICloneable
public class MyBaseClass
{...}
public class LinkedList where K : MyBaseClass
public class LinkedList where K : MyBaseClass, IComparable
3.构造函数约束
class Node where T : new()
{
public K Key;
public T Item;
public Node NextNode;
public Node()
{
Key = default(K);
Item = new T(); //构造函数使用.
NextNode = null;
}
}
public class LinkedList where K : IComparable
where T : ICloneable
public class MyBaseClass
{...}
public class LinkedList where K : MyBaseClass
public class LinkedList where K : MyBaseClass, IComparable
3.构造函数约束
class Node where T : new()
{
public K Key;
public T Item;
public Node NextNode;
public Node()
{
Key = default(K);
Item = new T(); //构造函数使用.
NextNode = null;
}
}
4.可以将构造函数约束与派生约束组合起来,前提是构造函数约束出现在约束列表中的最后:
public class LinkedList where K : IComparable,new()
5.引用/值类型约束
可以使用 struct 约束将一般类型参数约束为值类型(例如,int、bool 和 enum),或任何自定义结构:
public class MyClass where T : struct
{...}
//同样,可以使用 class 约束将一般类型参数约束为引用类型(类):
public class MyClass where T : class
{...}
{...}
//同样,可以使用 class 约束将一般类型参数约束为引用类型(类):
public class MyClass where T : class
{...}
6.编译器允许您将一般类型参数显式强制转换到其他任何接口,但不能将其转换到类:
代码
interface ISomeInterface
{...}
class SomeClass
{...}
class MyClass
{
void SomeMethod(T t)
{
ISomeInterface obj1 = (ISomeInterface)t;//Compiles
SomeClass obj2 = (SomeClass)t; //Does not compile
}
}
//7.代码块 6. 对一般类型参数使用“is”和“as”运算符
public class MyClass
{
public void SomeMethod(T t)
{
if(t is int)
{...}
if(t is LinkedList)
{...}
string str = t as string;
if(str != null)
{...}
LinkedList list = t as LinkedList;
if(list != null)
{...}
}
}
interface ISomeInterface
{...}
class SomeClass
{...}
class MyClass
{
void SomeMethod(T t)
{
ISomeInterface obj1 = (ISomeInterface)t;//Compiles
SomeClass obj2 = (SomeClass)t; //Does not compile
}
}
//7.代码块 6. 对一般类型参数使用“is”和“as”运算符
public class MyClass
{
public void SomeMethod(T t)
{
if(t is int)
{...}
if(t is LinkedList)
{...}
string str = t as string;
if(str != null)
{...}
LinkedList list = t as LinkedList;
if(list != null)
{...}
}
}
8.一般类型参数的转换.
泛型和强制类型转换
C# 编译器只允许将一般类型参数隐式强制转换到 Object 或约束指定的类型,如代码块 5 所示。这样的隐式强制类型转换是类型安全的,因为可以在编译时发现任何不兼容性。
代码块 5. 一般类型参数的隐式强制类型转换
代码
interface ISomeInterface
{...}
class BaseClass
{...}
class MyClass where T : BaseClass,ISomeInterface
{
void SomeMethod(T t)
{
ISomeInterface obj1 = t;
BaseClass obj2 = t;
object obj3 = t;
}
}
//编译器允许您将一般类型参数显式强制转换到其他任何接口,但不能将其转换到类:
interface ISomeInterface
{...}
class SomeClass
{...}
class MyClass
{
void SomeMethod(T t)
{
ISomeInterface obj1 = (ISomeInterface)t;//Compiles
SomeClass obj2 = (SomeClass)t; //Does not compile
}
}
interface ISomeInterface
{...}
class BaseClass
{...}
class MyClass where T : BaseClass,ISomeInterface
{
void SomeMethod(T t)
{
ISomeInterface obj1 = t;
BaseClass obj2 = t;
object obj3 = t;
}
}
//编译器允许您将一般类型参数显式强制转换到其他任何接口,但不能将其转换到类:
interface ISomeInterface
{...}
class SomeClass
{...}
class MyClass
{
void SomeMethod(T t)
{
ISomeInterface obj1 = (ISomeInterface)t;//Compiles
SomeClass obj2 = (SomeClass)t; //Does not compile
}
}
9.从泛型类继承的类,要指明具体的参数.
public class BaseClass<T>
{...}
public class SubClass : BaseClass<int>
{...}
{...}
public class SubClass : BaseClass<int>
{...}
10.如果子类也是泛类,基类的约束需要在子类重新规范一边
public class BaseClass<T> where T : ISomeInterface
{...}
public class SubClass<T> : BaseClass<T> where T : ISomeInterface
{...}
{...}
public class SubClass<T> : BaseClass<T> where T : ISomeInterface
{...}
//2.1
public class BaseClass<T> where T : ISomeInterface
{...}
public class SubClass<T> : BaseClass<T> where T : ISomeInterface
{...}
public class BaseClass<T> where T : ISomeInterface
{...}
public class SubClass<T> : BaseClass<T> where T : ISomeInterface
{...}
11 如果基类有泛型虚方法,子类可以重载,但是必须指明具体类型.
public class BaseClass<T>
{
public virtual T SomeMethod()
{...}
}
public class SubClass: BaseClass<int>
{
public override int SomeMethod()
{...}
}
{
public virtual T SomeMethod()
{...}
}
public class SubClass: BaseClass<int>
{
public override int SomeMethod()
{...}
}
12 但是如果子类也是泛型,则重载时也可使用子类的<T>:
public class SubClass<T>: BaseClass<T>
{
public override T SomeMethod()
{...}
}
{
public override T SomeMethod()
{...}
}
13. 泛类的其它泛型参数以及约束.
代码
public void Clone<T2>(T2 target)
where T2 : EBaseResItem<T2>
{
foreach (var property in AllProperties)
{
var pName = property.PropertyInfo.Name;
var p2 = EBaseResItem<T2>.AllProperties.FirstOrDefault(p => p.PropertyInfo.Name == pName);
if (p2 != null)
{
this.LoadProperty(property.PropertyInfo, target.ReadProperty(p2.PropertyInfo));
}
}
}
where T2 : EBaseResItem<T2>
{
foreach (var property in AllProperties)
{
var pName = property.PropertyInfo.Name;
var p2 = EBaseResItem<T2>.AllProperties.FirstOrDefault(p => p.PropertyInfo.Name == pName);
if (p2 != null)
{
this.LoadProperty(property.PropertyInfo, target.ReadProperty(p2.PropertyInfo));
}
}
}
14 可以定义泛型接口.
public interface ISomeInterface<T>
{
T SomeMethod(T t);
}
{
T SomeMethod(T t);
}