2011-12-04 39 views
3

我有一個面向對象問題,我認爲它可以與通用協方差關聯。我想建立一個模塊化系統導入不同類型的記錄...模塊包含了常用的方法,以及SalesModule包含用於處理特定的邏輯功能...通用協方差和鑄造到超類型

public interface IImportable { ... void BuildSqlDataRecord(); ... } 
public class Sales : IImportable { ... } 
public interface IModule<out T> where T : IImportable 
{ 
    void Import(IEnumerable<T> list); // Error Occurs here... 
    IEnumerable<T> LoadFromTextFile(TextReader sr); 
} 
public abstract class Module<T> : IModule<T> where T : IImportable 
{ 
    public void Import(IEnumerable<T> list) { ... T.BuildSqlDataRecord(); ... } 
    public IEnumerable<T> LoadFromTextFile(TextReader sr) { ... } 
} 
public class SalesModule : Module<Sales> 
{ 
    public override void BuildSqlDataRecord() { ... }; 
} 

,並在其他功能:

//Module<IImportable> module = null; 
IModule<IImportable> module = null; 
if(file.Name == "SALES") 
    module = new SalesModule(); 
else 
    module = new InventoryModule(); 

var list = module.LoadFromTextFile(sr); 
module.Import(list); 

如何聲明模塊以便我可以調用重寫的方法?

回答

10
public interface IModule<out T> where T : IImportable 
{ 
    void Import(IEnumerable<T> list); // Error Occurs here... 
    IEnumerable<T> LoadFromTextFile(TextReader sr); 
} 

錯誤是正確的。我們選擇「out」作爲表示協變性的關鍵字,提醒您T只能出現在「輸出」位置。在突出顯示的行中,T顯示爲輸入。

T必須不能是一個輸入,因爲......好吧,假設它被允許,看看有什麼不好的事情發生:

IModule<Giraffe> gm = GetMeAModuleOfGiraffes(); 
IModule<Animal> am = gm; // Legal because of covariance. 
IEnumerable<Tiger> tigers = GetMeASequenceOfTigers(); 
IEnumerable<Animal> animals = tigers; // Legal because of covariance. 
am.Import(animals); // Uh oh. 

您剛剛導入老虎列表到,只有知道如何處理模塊長頸鹿。

爲了防止這種情況發生,必須將非法步驟作爲第一步。類型聲明對於「out」是非法的。

如何聲明模塊以便我可以調用重寫的方法?

你必須聲明接口,以便它服從協方差規則。你如何做到這一點取決於你,但首先不要將任何「輸出」參數放入「輸入」位置。

+0

偉大的例子...現在,如何重構... :)謝謝! –

3

你需要使用一個接口爲您的模塊:

public interface IModule<out T> where T : IImportable 
{ 
    void DoStuff(); 
    void DoOtherStuff(); 
} 

然後你就可以宣佈你的模塊,像這樣:

IModule<IImportable> = null; 

out通用mdoifier見here for the MSDN documentation

+0

Rich - 感謝您的快速回答。我編輯了這個問題,爲這個例子添加了一些細節,可能會改變一些事情。我似乎無法實現您的更改,因爲協變參數T用作Import方法的輸入以及LoadFromTextFile的返回值。我是否完全錯誤? –