2016-09-13 119 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

非常感谢,现在你已经指出它如何被滥用,这是令人讨厌的理解。 –