1

What is a design rationale behind this:

OK:

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

WRONG:

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    public new void DoWork() { Console.WriteLine("B"); } //public doesn't
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

Why does non-virtual method interfere with overriding virtual method anyway?

1st case: compiler checks that the method is private (new) so it allows class C.DoWork() to override class A.DoWork() (does not mix virtual and not-virtual (B.DoWork()) methods).

2nd case: compiler sees that public (new) void is declared and it arbitrarily(?) disrupts overriding in class C.

Now, if I wanted to declare new virtual DoWork() I could have done it, if I wanted to disallow overriding, I could have used sealed specifier. But in this case I wrote public void DoWork() as declaring normal non-virtual method and I do not expect it participating in virtual inheritance chain as in the private case. In 2nd example I expect:

A ac = new C();
ac.DoWork();

to print C as in the private case.

TylerH
  • 20,799
  • 66
  • 75
  • 101
user206334
  • 850
  • 1
  • 8
  • 18

3 Answers3

0

In first example your C class ovverides A's DoWork (B had DoWork, which is private and not visible to subclasses). In second example you hide DoWork by non-virtual function and compiler complains, that you are trying to override non-virtual function. Solution is to expose families of virtual functions. By new virtual you can create separations between these families.

public class B : A
{
    public new virtual void DoWork() { Console.WriteLine("B"); } //private works
}

This code then

A a = new C();
a.DoWork();

prints A

B b = new C();
b.DoWork();

prints C

You can read in more detail how new virtual is used in Knowing When to Use Override and New Keywords. new keyword without virtual has a different semantics from new virtual, you can read more about it at new keyword in method signature.

Community
  • 1
  • 1
Ilya Ivanov
  • 23,148
  • 4
  • 64
  • 90
  • You are missing that there is NO virtual specified inside middle (B) class. Yes, new virtual in C# unlike C++ ends the chain of virtual dispatch, but in this case b.DoWork() is not virtual at all. – user206334 Jan 25 '13 at 09:47
  • So the base class has `virtual` keyword so `DoWork` is virtual and can't be hidden in subclasses without `virtual` specifier. – Ilya Ivanov Jan 25 '13 at 09:49
0

Because in first case you're overriding an A class function and not B one

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); } //OVERRIDES A.DoWork()
}

You can not override non virtual/abstract methods of the base class.

Tigran
  • 61,654
  • 8
  • 86
  • 123
0

In below code

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

you are telling the compiler that DoWork() method in B class is a new version of class A's DoWork() method. However, it allows you to override DoWork in C due to the fact that you have declared DoWork's new version as private in B which makes the compiler assume that that method is not exposed to the outside world.

However, in this,

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    public new void DoWork() { Console.WriteLine("B"); } //public
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

You are telling the compiler to override new version of method DoWork(), which is a bit wrong from compiler's point of view as it cannot override a non abstract/virtual/overriden method as per the rules set while designing the language.

That is why, I think, your code gives error in one case and not the other.

mihirj
  • 1,199
  • 9
  • 15