C# 委托方差和泛型

C# delegate variance and generics

在下面的代码中,我想使用一个具有更多派生参数的动作传递到一个使用基数作为参数的动作中。代码如下所示:

public interface IContext<T>
{
}

public interface IWorkflow<T>
{
    void Do(Action<IContext<T>> lambda);
}


public interface IDerivedContext : IContext<int>
{

}

public interface IDerivedWorkflow : IWorkflow<int>
{
    void Do(Action<IDerivedContext> lambda);
}

public class Workflow<T> : IWorkflow<T>
{
    public void Do(Action<IContext<T>> lambda)
    {
        Console.WriteLine("in Do(Action<IContext<T>>");
    }
}

public class DerivedContext : IContext<int>
{
}

public class DerivedWorkflow : Workflow<int>, IDerivedWorkflow
{
    public void Do(Action<IDerivedContext> lambda)
    {
        base.Do(lambda); // Compiler error:
    }
}

如果我投下这条线:

        base.Do(lambda);

像这样:

        base.Do((Action<IContext<int>>)lambda); 

编译器接受转换,但代码在运行时失败并出现 InvalidCastException。

根据 MSDN 文档,它表明上述内容应该有效,因为我将一个参数为更多派生 class 的动作传递给一个使用最少派生 class 参数的动作](在本例中为基数 class)例如文档说明了以下内容:

static void AddToContacts(Person person)
{
    // This method adds a Person object
    // to a contact list.
}

static void Test()
{
    // Create an instance of the delegate without using variance.
    Action<Person> addPersonToContacts = AddToContacts;

    // The Action delegate expects 
    // a method that has an Employee parameter,
    // but you can assign it a method that has a Person parameter
    // because Employee derives from Person.
    Action<Employee> addEmployeeToContacts = AddToContacts;
 }

}

我是不是误会了什么,或者是否有解决此问题的方法。

提前致谢

这根本不安全;你不能那样做。

一个Action<IDerivedContext>只能接受一个IDerivedContext作为参数。如果您能够将它转换为 Action<IContext<int>>,您将能够使用它实际上无法接受的其他一些 IContext<int> 实现来调用它。