Home > OS >  "CS0109: The member 'member' does not hide an inherited member. The new keyword is no
"CS0109: The member 'member' does not hide an inherited member. The new keyword is no

Time:12-20

I've read other threads and Eric Lippert's posts on the subject, but haven't seen this exact situation addressed anywhere. C# optional parameters on overridden methods Optional parameters and inheritance

I'm trying to implement the following situation:

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
  }
}

When I do this the compiler gives me the warning in the subject line that I do not need to use the new keyword because the method does not hide the inherited method. However I do not see a way to call the base method from the object instance, so it looks hidden to me.

I want it to actually be hidden. If it is not hidden, there is potential for some other user to some day call the base method directly and break the class (it involves thread safety).

My question is, does the new method actually hide the inherited method (compiler is wrong?) or is the compiler correct and I need to do something else to hide the original method? Or is it just not possible to achieve the desired outcome?

CodePudding user response:

  • void DoThings(String str) accepts a single parameter
  • void DoThings(String str, Int32 someint = 1) accepts two parameters

=> the methods are distinct, unrelated methods, which incidentally share the name.

Default parameters are inserted at the call-sites during compilation.

Here is one possible solution:

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
  }
}

Note that new makes it possible to call base classes' virtual methods in the first place by having a reference with static type of the base class (e.g. by casting it to the base class):

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);
  }
}

Output:

derived: a
base: a
base: b
base: c

If you want callers to never call the overridden method of a base class, mark it virtual and override it (like already shown at the top of this answer):

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);
  }
}

Output:

derived: a
base: a
derived: b
base: b
derived: c
base: c

After discussion in the comments: you do not want to use inheratince here, but rather opt for compisition.

The code could look like the following:

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);
  }
}

Output:

base: a
wrapped: a

CodePudding user response:

  1. the 'new' keyword can't be used where you used it

  2. To hide the member:

    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)

    {

     //dostuff but including someint, calls base:DoThings in here
    

    }

    }

  • Related