# 关于委托怎么匹配的问题，以及逆变和协变

• ### 问题

• 看了一下msdn里面关于逆变和协变的章节，在委托 那一章里面又一个疑问

代码如下：

```public class First { }
public class Second : First { }
public delegate First SampleDelegate(Second a);
public delegate R SampleGenericDelegate<A, R>(A a);

// Matching signature.
public static First ASecondRFirst(Second first)
{ return new First(); }

// The return type is more derived.
public static Second ASecondRSecond(Second second)
{ return new Second(); }

// The argument type is less derived.
public static First AFirstRFirst(First first)
{ return new First(); }

// The return type is more derived
// and the argument type is less derived.
public static Second AFirstRSecond(First first)
{ return new Second(); }
// Assigning a method with a matching signature
// to a non-generic delegate. No conversion is necessary.
SampleDelegate dNonGeneric = ASecondRFirst;
// Assigning a method with a more derived return type
// and less derived argument type to a non-generic delegate.
// The implicit conversion is used.
SampleDelegate dNonGenericConversion = AFirstRSecond;    //         <-这一块有问题

// Assigning a method with a matching signature to a generic delegate.
// No conversion is necessary.
SampleGenericDelegate<Second, First> dGeneric = ASecondRFirst;
// Assigning a method with a more derived return type
// and less derived argument type to a generic delegate.
// The implicit conversion is used.
SampleGenericDelegate<Second, First> dGenericConversion = AFirstRSecond;

```

如题那块上面的注释所说，分派了一个方法，它的返回值类型是原类型的derived輩，它的参数类型是是原类型的base輩。  然后发生了隐式转换和delegate相匹配。

1.这是否是逆变和协变。如果是逆变和协变是否是默认可以的？因为子类转成父类可以理解(也就是协变)，但是父类转为子类也可以吗？

2.我尝试了一下其他的

定义了委托和方法

`public delegate First FFDelegate(First f);public static Second RSecondASecond(Second s){	return new Second();	}public static First RFirstASecond(Second s){	return new First();	}public static Second RSecondAFirst(First f){	return new Second();	}`

发现

`FFDelegate FFssDele = RSecondASecond;   //error报错，为什么呢，他不是会发生自动转换的吗?FFDelegate FFFSDele = RFirstASecond;	//error FFDelegate FFSFDele = RSecondAFirst;	//但是这个却成功了，难道是返回值可以自动转换，而参数不可以吗？`

2013年2月8日 14:32

### 答案

• 委托必须是“参数”至少是同一类型，或者是其子类。但是究其本质还是存在协变和逆变的问题。

简单来说——

FFDelegateFFssDele=RSecondASecond;

你在使用这个委托的时候肯定是：

FFssDele(传入一个First类型的实体对象）。

问题在于：Second继承于First，那么如果First还有其它子类呢（譬如说First还有一个Third的子类），

你照样可以传送一个third实体进来，但是third和second毫无关系，你怎么把thrid转化成second（右边那个second的委托函数呢？）

至于说第三个为什么可以，是因为它在语法上完全符合委托的参数，同时返回值也是First的子类，是可以相互转换。

```namespace CSharp
{
/// <summary>
/// 保证父类K只能作为输入，不能用于输出；V只能输出，不能输入
/// </summary>
public delegate V MyDel<in K,out V>(K key)where K:V;

class First
{
}
class Second : First
{
}

class Program
{
public static Second RSecondASecond(Second s)
{ return new Second(); }
public static First RFirstASecond(Second s)
{ return new First(); }
public static Second RSecondAFirst(First f)
{ return new Second(); }

static void Main(string[] args)
{
MyDel<Second, First> f = new MyDel<Second, Second>(RSecondASecond);
}

}
}```
还可以参考：http://msdn.microsoft.com/zh-cn/library/ms173174(VS.80).aspx
2013年2月9日 2:57