C#委托方差和泛型

时间:2016-07-10 23:17:04

标签: c# generics delegates variance

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

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文档,它建议上面的内容应该有效,因为我将一个带有更多派生类参数的Action传递给一个Action,它使用一个派生类最少的参数(在本例中是基类)例如,文档说明了以下内容:

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;
 }

}

我是否误解了某些问题或是否有解决此问题的方法。

提前致谢

1 个答案:

答案 0 :(得分:0)

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

Action<IDerivedContext>只能将IDerivedContext作为参数。如果您能够将其转换为Action<IContext<int>>,则可以使用其他IContext<int>实施方式将其调用,但它实际上无法接受。