我读过其他帖子和埃里克·利珀特(Eric Lippert)关于该主题的帖子,但没有在任何地方看到这种确切情况的解决。 重写方法上的 C# 可选参数 可选参数和继承
我正在尝试实现以下情况:
public class BaseClass
{//ignore rest of class for now
public void DoThings(String str)
{
//dostuff
}
}
public class DerivedClass: BaseClass
{//ignore rest of class for now
new public void DoThings(String str, Int32 someint = 1)
{
//dostuff but including someint, calls base:DoThings in here
}
}
当我这样做时,编译器会在主题行中向我发出警告,表明我不需要使用 new 关键字,因为该方法不会隐藏继承的方法。但是我没有看到从对象实例调用基本方法的方法,所以它对我来说看起来是隐藏的。
我希望它实际上被隐藏。如果不隐藏,其他用户有可能有一天直接调用基方法并破坏类(这涉及线程安全)。
我的问题是,新方法实际上隐藏了继承的方法(编译器错误?)还是编译器正确,我需要做其他事情来隐藏原始方法?还是根本不可能达到预期的结果?
void DoThings(String str)
接受单个参数void DoThings(String str, Int32 someint = 1)
接受两个参数=> 这些方法是不同的、不相关的方法,顺便共享名称。
默认参数在编译期间插入到call-sites。
这是一种可能的解决方案:
public class BaseClass
{
public virtual void DoThings(String str)
{
//dostuff
}
}
public class DerivedClass: BaseClass
{
public override void DoThings(String str)
{
DoThings(str, 1); // delegate with default param
}
public void DoThings(String str, Int32 someint)
{
//dostuff
}
}
请注意,
new
使得可以通过引用基类的静态类型(例如,通过将其强制转换为基类)来首先调用基类的虚拟方法:
public class Test
{
public static void Main()
{
var obj = new DerivedClass();
BaseClass baseObj = obj;
obj.DoThings("a");
baseObj.DoThings("b");
((BaseClass)obj).DoThings("c");
}
}
class BaseClass
{
public void DoThings(String str)
{
Console.WriteLine("base: " + str);
}
}
class DerivedClass: BaseClass
{
new public void DoThings(String str, Int32 someint = 1)
{
Console.WriteLine("derived: " + str);
base.DoThings(str);
}
}
输出:
derived: a
base: a
base: b
base: c
如果您希望调用者永远不会调用基类的overridden
方法,请将其标记为 virtual
和
override
(如本答案顶部所示):public class Test
{
public static void Main()
{
var obj = new DerivedClass();
BaseClass baseObj = obj;
obj.DoThings("a");
baseObj.DoThings("b");
((BaseClass)obj).DoThings("c");
}
}
class BaseClass
{
public virtual void DoThings(String str)
{
Console.WriteLine("base: " + str);
}
}
class DerivedClass: BaseClass
{
// "hide" (override) your base method:
public override void DoThings(String str)
{
// delegate to method with default param:
this.DoThings(str);
}
public void DoThings(String str, Int32 someint = 1)
{
Console.WriteLine("derived: " + str);
base.DoThings(str);
}
}
输出:
derived: a
base: a
derived: b
base: b
derived: c
base: c
代码可能如下所示:
public class Test
{
public static void Main()
{
var obj = new DerivedClass(new BaseClass());
obj.DoThings("a");
// baseObj.DoThings("b"); // not accessible
// ((BaseClass)obj).DoThings("c"); // InvalidCastException!
}
}
class BaseClass
{
public void DoThings(String str)
{
Console.WriteLine("base: " + str);
}
}
class Wrapper
{
private BaseClass original;
public Wrapper(BaseClass original) {
this.original = original;
}
public void DoThings(String str, Int32 someint = 1)
{
Console.WriteLine("wrapped: " + str);
original.DoThings(str);
}
}
输出:
base: a
wrapped: a
public class BaseClass
{ // ignore rest of class for now
public virtual void DoThings(String str)
{
// dostuff
}
}
public class DerivedClass: BaseClass
{ //ignore rest of class for now
public override void DoThings(String str)
{
// dostuff
}
public void DoThings(String str, Int32 someint = 1)
{
// do stuff but including some int, calls base:DoThings in here
}
}