2016-07-10 106 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 可能有一個完全不同的繼承分支。 –