变体泛型

变体泛型接口(Variant Generic Interfaces)

协变 out

可以将具有派生程度更大(更具体)的类型的泛型,转为具有派生程度更小(更抽象)的类型的泛型

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public interface ICovariant<out T>
{
T GetSome();

void Todo(Action<T> action);
}

public class MyCovariant<T> : ICovariant<T>
{
public T GetSome()
{
return default<T>;
}

public void Todo(Action<T> action)
{

}
}

public class Base
{

}


public class Child : Base
{

}

public class Program
{
public static void Main(string[] args)
{
// 子类更具体
ICovariant<Child> childs = new MyCovariant<Child>();

// 基类更抽象,从具体到抽象的隐式转换
ICovariant<Base> bases = childs;
}
}

逆变 in

可以将具有派生程度更小(更抽象)的类型的泛型,转为具有派生程度更大(更具体)的类型的泛型

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public interface IContravariant<in T>
{
void SetSome(T param);

void Todo(Func<T> action);
}

public class MyContravariant<T> : IContravariant<T>
{
public void SetSome(T param)
{

}

public void Todo(Func<T> action)
{

}
}

public class Base
{

}


public class Child : Base
{

}

public class Program
{
public static void Main(string[] args)
{
// 基类更抽象
IContravariant<Base> bases = new MyContravariant<Base>();

// 子类更具体,从抽象到具体的隐式转换
IContravariant<Child> childs = bases;
}
}

PS:

协变和逆变属于可变泛型,常规的泛型属于固定泛型;
可变泛型仅可在接口和委托之间转换,无法在其实现类上转换,因为可变泛型接口的实现类为固定泛型。