C# 逆变委托输出结果

C# 逆变委托输出结果,c#,delegates,covariance,C#,Delegates,Covariance,我将类层次结构定义为Object->Fruit->Apple class Fruit : object{} class Apple : Fruit{} 并创建了两个静态方法来处理这些类 static Fruit FruitProcessor(string fruit) { return new Fruit(); } static Apple ApplesProcessor(string apple) { return

我将类层次结构定义为Object->Fruit->Apple

class Fruit : object{}

class Apple : Fruit{}
并创建了两个静态方法来处理这些类

    static Fruit FruitProcessor(string fruit)
    {
        return new Fruit();
    }

    static Apple ApplesProcessor(string apple)
    {
        return new Apple();
    }
现在我声明了一个委托,没有任何
in,out
关键字

public delegate TResult Funk<T, TResult>(T arg);
一切都和以前一样


怎么可能呢?

像这样的情况是通过通常的隐式转换来处理的。引用相关MSDN页面():

公共类优先{}
公共类第二类:第一类{}
公共代表第一个样本代表(第二个a);
公共代表R样本一般代表(A);
//匹配的签名。
公共静态第一个ASecondRFirst(第二个第一个)
{返回新的第一个();}
//返回类型更加派生。
公共静态秒aseconds(秒)
{返回新的第二个();}
//参数类型派生较少。
公共静态First affirstrfirst(First First)
{返回新的第一个();}
//返回类型更加派生
//并且参数类型派生较少。
公共静态秒AFirstRSecond(第一个)
{返回新的第二个();}
//为方法分配匹配的签名
//给非泛型委托。不需要转换。
SampleDelegate dNonGeneric=第二个或第一个;
//指定具有更派生的返回类型的方法
//和非泛型委托的派生参数类型较少。
//使用隐式转换。
SampleDelegate dNonGenericConversion=第一秒;
//将具有匹配签名的方法分配给泛型委托。
//不需要转换。
SampleGenericDelegate dGeneric=ASecondRFirst;
//指定具有更派生的返回类型的方法
//和泛型委托的派生参数类型较少。
//使用隐式转换。
SampleGenericDelegate dGenericConversion=AFirstRSecond;
简而言之,在您的确切情况下,您将非泛型委托分配给泛型委托-在这种情况下始终使用隐式转换。要使代码真正失败,您需要执行以下操作:

Funk<string, Fruit> myFunc;
Funk<string, Apple> myAppleFunc = ApplesProcessor;
myFunc = FruitProcessor;
myFunc = myAppleFunc; // Undefined implicit conversion on generic delegate
Funk myFunc;
Funk myAppleFunc=应用处理器;
myFunc=处理器;
myFunc=myAppleFunc;//泛型委托上未定义的隐式转换

这样的情况由通常的隐式转换处理。引用相关MSDN页面():

公共类优先{}
公共类第二类:第一类{}
公共代表第一个样本代表(第二个a);
公共代表R样本一般代表(A);
//匹配的签名。
公共静态第一个ASecondRFirst(第二个第一个)
{返回新的第一个();}
//返回类型更加派生。
公共静态秒aseconds(秒)
{返回新的第二个();}
//参数类型派生较少。
公共静态First affirstrfirst(First First)
{返回新的第一个();}
//返回类型更加派生
//并且参数类型派生较少。
公共静态秒AFirstRSecond(第一个)
{返回新的第二个();}
//为方法分配匹配的签名
//给非泛型委托。不需要转换。
SampleDelegate dNonGeneric=第二个或第一个;
//指定具有更派生的返回类型的方法
//和非泛型委托的派生参数类型较少。
//使用隐式转换。
SampleDelegate dNonGenericConversion=第一秒;
//将具有匹配签名的方法分配给泛型委托。
//不需要转换。
SampleGenericDelegate dGeneric=ASecondRFirst;
//指定具有更派生的返回类型的方法
//和泛型委托的派生参数类型较少。
//使用隐式转换。
SampleGenericDelegate dGenericConversion=AFirstRSecond;
简而言之,在您的确切情况下,您将非泛型委托分配给泛型委托-在这种情况下始终使用隐式转换。要使代码真正失败,您需要执行以下操作:

Funk<string, Fruit> myFunc;
Funk<string, Apple> myAppleFunc = ApplesProcessor;
myFunc = FruitProcessor;
myFunc = myAppleFunc; // Undefined implicit conversion on generic delegate
Funk myFunc;
Funk myAppleFunc=应用处理器;
myFunc=处理器;
myFunc=myAppleFunc;//泛型委托上未定义的隐式转换
根据代表返回类型的协方差和代表输入类型的逆变换,从.NET 3.5开始就暗示了这一点。因此,将
输入
输出
添加到您的代理中没有任何区别

添加此选项的一个原因是,您可以将接受
EventArgs
参数的“普通”事件处理程序分配给可能使用从
EventArgs
派生的更特定类的多个事件。例如,您可以使用同一个代理来处理按钮单击和按键操作,即使前者传递一个
MouseEventArgs
参数,而后者传递一个
KeyEventArgs
参数。

根据代理返回类型的协方差和代理输入类型的协方差,从.NET 3.5开始就隐含了。因此,将
输入
输出
添加到您的代理中没有任何区别


添加此选项的一个原因是,您可以将接受
EventArgs
参数的“普通”事件处理程序分配给可能使用从
EventArgs
派生的更特定类的多个事件。例如,您可以使用同一个委托来处理按钮单击和按键操作,即使前者传递一个
MouseEventArgs
参数,而后者传递一个
KeyEventArgs
参数。

这不是很好,而是使用方法而不是lambdas吗?我认为这两个问题都包含在被链接为重复的问题中。。。?如果你使用的是lambda,你可以让签名匹配,所以你必须让它匹配?但是对于方法来说,这不是强制的吗?这是一个稍微不同的问题。前一个是关于反义函数的特殊解释。这似乎是由.NET3.5更改引起的。这不是很常见,而是使用方法而不是lambdas吗?我认为这两个问题都包含在被链接为重复的问题中。。。?如果你用的是lambda,你可以让签名匹配,所以哟
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;
Funk<string, Fruit> myFunc;
Funk<string, Apple> myAppleFunc = ApplesProcessor;
myFunc = FruitProcessor;
myFunc = myAppleFunc; // Undefined implicit conversion on generic delegate