C# 超越变量函数

C# 超越变量函数,c#,overriding,abstract,variadic,C#,Overriding,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.WriteLin

我很难重写一个变量函数。例子比语言更有价值,让我们举个例子:

这是我的抽象类:

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 
}
但是当我编译时,我有一个错误,说没有找到合适的方法来覆盖DoSomething(int,int,string)

我是否有可能或必须找到解决办法


谢谢

重写方法时,签名必须相同。你不能“发明”一个新的签名

public override MyType DoSomething(params Object[] objs)
{
    // do something
}
你在这里无能为力


因此,您必须决定希望您的方法具有什么签名,并使用它。您甚至可以在
MyClass

中保留这两个签名。当您重写一个方法时,签名必须相同。你不能“发明”一个新的签名

public override MyType DoSomething(params Object[] objs)
{
    // do something
}
你在这里无能为力


因此,您必须决定希望您的方法具有什么签名,并使用它。您甚至可以将这两个签名保留在
MyClass
DoSomething
myoverridtenclass
不能覆盖
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
=
Base
TParam
=
TParam2
。同时,正确性要求不那么严格。它只需要
TReturn:Base
,以及
TParam:TParam2
(注意它们是翻转的)

要了解原因,请举个例子

Base b = new Derived()
Base newbase = d.example(default(TParam))
它必须返回一个适合于
Base
的值。它还可以接受任何可以提供给
Base.example
的参数。如果它需要更具体的参数,那么你就被套住了,因为编译器不知道(也不知道也不应该知道)
b
派生的类型

现在回到变量方法。可以想象,有些语言不是C语言,但看起来确实允许这样做。同样可以想象的是,这样一种不是C语言的语言,在分解变量方法时有一些语法上的糖分,下面的内容可以来回转换:

public T Example(params object[] objs)

public T Example2(object obj1, object obj2)
但是派生类型中的实现在其参数列表中应该不那么具体,而不是更具体。因此,这种(非C)语言所能做的最好的事情就是允许您重写,例如

public T Example(params SpecificType[] values)

但决不能反过来

tl;博士:


语言不允许这样做,也不允许这样做,因为这会破坏替换原则。

MyOverridtenClass中的
DoSomething
无法重写
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
=
Base
TParam
=
TParam2
。同时,正确性要求不那么严格。它只需要
TReturn:Base
,以及
TParam:TParam2
(注意它们是翻转的)

要了解原因,请举个例子

Base b = new Derived()
Base newbase = d.example(default(TParam))
它必须返回一个适合于
Base
的值。它还可以接受任何可以提供给
Base.example
的参数。如果它需要更具体的参数,那么你就被套住了,因为编译器不知道(也不知道也不应该知道)
b
派生的类型

现在回到变量方法。可以想象,有些语言不是C语言,但看起来确实允许这样做。同样可以想象的是,这样一种不是C语言的语言,在分解变量方法时有一些语法上的糖分,下面的内容可以来回转换:

public T Example(params object[] objs)

public T Example2(object obj1, object obj2)
但是派生类型中的实现在其参数列表中应该不那么具体,而不是更具体。因此,这种(非C)语言所能做的最好的事情就是允许您重写,例如

public T Example(params SpecificType[] values)

但决不能反过来

tl;博士:


语言不允许这样做,也不允许这样做,因为这会破坏替换原则。

非常好的解释!谢谢:)很好的解释!谢谢:)