覆盖可变参数函数

时间:2015-05-29 08:34:44

标签: c# override abstract variadic

我无法覆盖变量函数。比值得更好的例子,让我们举一个例子:

这是我的抽象类:

public abstract class MyClass<T> {
    public abstract T DoSomething(params Object[] objs);
    public void ShowSomething(List<T> items){
        foreach(T it in items){
            Console.WriteLine(string.Format("{0},{1},{2}",it.propA,it.propB,it.propC));
        }
    }
    // Other things 
}

这是我试图覆盖它:

public class MyOverridenClass : MyClass<MyType> {
    public override MyType DoSomething(int a, int b, string c){
        return new MyType(){ propA = a+b, propB = a-b, propC = c+""+a};
     }
}

从我的主人那里:

public static void Main(string[] args){
    MyOverridenClass cl = new MyOverridenClass();
    List<MyType> lst = new List<MyType>();
    lst.Add(cl.DoSomething(1,2,"foo"));
    cl.ShowSomething();
}

我希望它输出:

3,-1,foo1

但是当我编译时,我有一个错误,说没有找到合适的方法来覆盖DoSomething(int,int,string)。

是否可能或者我必须找到解决方法?

谢谢!

2 个答案:

答案 0 :(得分:3)

覆盖方法时,签名必须相同。你不能发明&#34;一个新的签名。

public override MyType DoSomething(params Object[] objs)
{
    // do something
}

你在这里无能为力......

因此,您必须决定您希望方法具有哪种签名,并使用它。您甚至可以在MyClass<T>

中保留这两个签名

答案 1 :(得分:1)

DoSomething中的

MyOverriddenClass无法覆盖DoSomething(params Object[] objs),因为您无法覆盖具有非可变参数的可变参数函数。

为什么不是这样的简单回答是因为规范是这样说的。但是,在一种不是C#的想象语言中,这仍然不起作用,因为实施方法不如基本方法具体,违反了合同。

在C#中,签名必须在覆盖时完全匹配,但这不是正确性所必需的。为了正确,方法实现合同就足够了。

例如,这是一个基类,它返回Base类型的东西,并将一个对象作为参数。

public class Base {
  public Base example(TParam obj)
}

如果我们要覆盖示例,我们需要它更具体才能正确

public class Derived : Base { 
  override public TReturn example(TParam2 obj) //this is illegal in C#
}

C#需要TReturn == BaseTParam == TParam2。同时,正确性要求不那么严格。它只需要TReturn : BaseTParam : TParam2(请注意它们被翻转)

要了解原因,请以

为例
Base b = new Derived()
Base newbase = d.example(default(TParam))

它必须返回一个符合&#34;适合&#34;在Base。它也最需要任何可以输入Base.example的参数。如果它需要更多特定的参数,那么你就会被软化,因为编译器不知道(并且不能知道并且不应该知道){{ 1}}类型为b

现在回到可变方法。可以想象,某种语言不是C#但看起来像它确实允许这样做。可以想象的是,这种不是C#的语言在分解可变方法时会有一些语法糖,而且可以来回传递以下内容:

Derived

但派生类型中的实现应始终在其参数列表中不太具体,而不是更具体。因此,这种(非C#)语言可以做的最好的就是允许你覆盖,例如,

public T Example(params object[] objs)

public T Example2(object obj1, object obj2)

public T Example(params SpecificType[] values)

public T Example(params object[] objs)

但从来没有反过来。

TL; DR:

语言不允许这样做,并且不能允许这样做,因为它会破坏替换原则。