“CS0109:成员“member”不隐藏继承的成员。不需要 new 关键字” - 这实际上是真的吗?

问题描述 投票:0回答:2

我读过其他帖子和埃里克·利珀特(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 关键字,因为该方法不会隐藏继承的方法。但是我没有看到从对象实例调用基本方法的方法,所以它对我来说看起来是隐藏的。

我希望它实际上被隐藏。如果不隐藏,其他用户有可能有一天直接调用基方法并破坏类(这涉及线程安全)。

我的问题是,新方法实际上隐藏了继承的方法(编译器错误?)还是编译器正确,我需要做其他事情来隐藏原始方法?还是根本不可能达到预期的结果?

c# inheritance overriding compiler-warnings
2个回答
8
投票
  • 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



0
投票
“new”关键字不能在您使用过的地方使用
  1. 隐藏成员:
  2. 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 } }
© www.soinside.com 2019 - 2024. All rights reserved.