2016-07-10 67 views
0

在下面的代码中,我想要使用一个具有更多派生参数传递的动作,将动作使用基本作为参数。代码如下所示:C#委托方差和泛型

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,例如文档说明了以下内容:

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

}

我误解的东西还是有一个解决此问题的。

在此先感谢

回答

0

这基本上是不安全的;你不能那样做。

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

+0

我想我需要一个巴掌向上醒来。我看不出问题所在,因为问题的范围只能从IContext 这个继承范例中缩小。你现在的答案可以帮助我明白为什么这是不安全的,因为从IContext 可能有一个完全不同的继承分支。 –