约束 | 描述 |
---|---|
where T: struct | 类型参数必须为值类型 |
where T : class | 类型参数必须为引用类型 |
where T : new() | 类型参数必须有一个公有、无参的构造函数。当于其它约束联合使用时,new()约束必须放在最后。 |
where T : <base class name> | 类型参数必须是指定的基类型或是派生自指定的基类型 |
where T : <interface name> | 类型参数必须是指定的接口或是指定接口的实现。可以指定多个接口约束。接口约束也可以是泛型的 |
示例
![](https://img.haomeiwen.com/i7643202/71646fdd77584d18.png)
Play函数传入的参数必须满足
- 参数为引用类型
- 必须是CustomClass01的子类或者派生类
- 必须含有无参构造函数
- 必须继承Iplay接口
public class CustomClass01
{
public int id;
}
public interface IPlay
{
void PlayGame();
}
public class CustomGeneric
{
public void Play<T>(T parameter) where T : CustomClass01, IPlay,new()
{
int Tempi = parameter.id;
parameter.PlayGame();
parameter = null;
}
}
协变&&逆变
在具有继承关系的两个类 Father(基类)和Son(派生类)中,会出现如下编译错误
![](https://img.haomeiwen.com/i7643202/b5b801ba1a2d0696.png)
常规泛型解决办法
![](https://img.haomeiwen.com/i7643202/bc2754aa3b798286.png)
List<Father> FatherList3 = new List<Son>().Select(c => (Father)c).ToList();
但是使用协变和逆变可解决上面的问题
![](https://img.haomeiwen.com/i7643202/5bd9132bf215c29c.png)
协变与逆变也有他们对应的约束
- 协变 out 只能是返回结果 修饰返回值
- 逆变 in 只能是参数 修饰传入参数
- 协变逆变 只能放在接口或者委托的泛型参数前面
相应全部代码
/// <summary>
/// .net4.0
/// 只能放在接口或者委托的泛型参数前面
/// out 协变covariant 修饰返回值
/// in 逆变contravariant 修饰传入参数
/// </summary>
public class Test
{
public static void Show()
{
{
Father bird1 = new Father();
Father bird2 = new Son();
Son Son1 = new Son();
//Son Son2 = new Father();
}
{
List<Father> birdList1 = new List<Father>();
//List<Father> FatherList2 = new List<Son>();
List<Father> FatherList3 = new List<Son>().Select(c => (Father)c).ToList();
}
{
//协变
IEnumerable<Father> FatherList1 = new List<Father>();
IEnumerable<Father> FatherList2 = new List<Son>();
Func<Father> func = new Func<Son>(() => null);
ICustomerListOut<Father> customerList1 = new CustomerListOut<Father>();
ICustomerListOut<Father> customerList2 = new CustomerListOut<Son>();
}
{//逆变
ICustomerListIn<Son> customerList2 = new CustomerListIn<Son>();
ICustomerListIn<Son> customerList1 = new CustomerListIn<Father>();
ICustomerListIn<Father> FatherList1 = new CustomerListIn<Father>();
FatherList1.Show(new Son());
FatherList1.Show(new Father());
Action<Son> act = new Action<Father>((Father i) => { });
}
{
IMyList<Son, Father> myList1 = new MyList<Son, Father>();
IMyList<Son, Father> myList2 = new MyList<Son, Son>();//协变
IMyList<Son, Father> myList3 = new MyList<Father, Father>();//逆变
IMyList<Son, Father> myList4 = new MyList<Father, Son>();//逆变+协变
}
}
}
public class Father
{
public int Id { get; set; }
}
public class Son : Father
{
public string Name { get; set; }
}
/// <summary>
/// 逆变in只能是参数
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListIn<in T>
{
void Show(T t);
}
public class CustomerListIn<T> : ICustomerListIn<T>
{
public void Show(T t)
{
}
}
/// <summary>
/// out 协变 只能是返回结果
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListOut<out T>
{
T Get();
}
public class CustomerListOut<T> : ICustomerListOut<T>
{
public T Get()
{
return default(T);
}
}
public interface IMyList<in inT, out outT>
{
void Show(inT t);
outT Get();
outT Do(inT t);
////out 只能是返回值 in只能是参数
}
public class MyList<T1, T2> : IMyList<T1, T2>
{
public void Show(T1 t)
{
Console.WriteLine(t.GetType().Name);
}
public T2 Get()
{
Console.WriteLine(typeof(T2).Name);
return default(T2);
}
public T2 Do(T1 t)
{
Console.WriteLine(t.GetType().Name);
Console.WriteLine(typeof(T2).Name);
return default(T2);
}
}
网友评论