2016-09-13 64 views
1

廣義方法我有以下代碼...不能通過派生類接受通用基礎類

using System; 

public interface ICommand<in TArgs> 
    where TArgs : BaseArgs 
{ 
    void Execute(); 
    void Execute(TArgs args); 
} 

public class BaseArgs 
{ } 

public abstract class BaseCommand<TArgs> : ICommand<TArgs> 
    where TArgs : BaseArgs 
{ 
    public void Execute() 
    { 
     var args = this.CreateArgs(); 
     this.Execute(args); 
    } 

    public void Execute(TArgs args) 
    { 
     this.GetData(args); 
    } 

    protected abstract void GetData(TArgs args); 
    protected abstract TArgs CreateArgs(); 
} 

public class ActualArgs : BaseArgs 
{ } 

public class ActualCommand : BaseCommand<ActualArgs> 
{ 
    protected override void GetData(ActualArgs args) 
    { 
     var messenger = new Messenger(this.Execute); 
     var m2 = new Messenger2(this); 
    } 

    protected override ActualArgs CreateArgs() 
    { 
     return new ActualArgs(); 
    } 
} 

public class Messenger 
{ 
    public Messenger(Action caller) 
    { 
     caller(); 
    } 
} 

public class Messenger2 
{ 
    public Messenger2(BaseCommand<BaseArgs> caller) 
    { 
     caller.Execute(); 
    } 
} 

理想我想使用Messenger2ActualCommand行抱怨說,它不能投ActualCommand<ActualArgs>BaseCommand<BaseArgs>,我真的不想申報Messenger2作爲

new Messenger2<ActualCommand<ActualArgs>>(this) 
+0

是'公衆Messenger2(BaseCommand 調用者)'可以接受嗎? – slawekwin

+0

不,因爲我會有很多從BaseCommand派生的命令,每個命令都會有自己的Args對象 –

回答

2

這並不原因有二:

  1. 只有通用接口可以做成協變(或逆變)。你的參數是抽象基類,而不是接口。
  2. 你的界面不是(也不能)是協變的。

假設這實際上編譯 - 你會允許這樣做:

BaseCommand<BaseArgs> command = new ActualCommand(); 

command.Execute(new SomeOtherArgsDerivedFromBaseArgs()); 

必須給你一些例外,如ActualCommand不知道如何處理以外的任何其他東西,是或者可以投射到ActualArgs

+0

非常感謝,現在你已經指出它如何被濫用,這是令人討厭的理解。 –