It's because
a
is a ClassA variable: it only "knows" about ClassA and overrides in derived classes.
In ClassB, the Print method is overridden, so when you try to call Print on
a
it searches for the highest level override it can find - but since ClassC doesn't override it in favour of hiding the existing implementations, it can't find it - it's not in the override inheritance chanin any more.
So it calls the ClassB.Print, and you get the result you see.
To check it, try this:
classC c = new classC();
classA a = c;
Console.WriteLine(a.Print());
Console.WriteLine(c.Print());
This explains it pretty well:
Knowing When to Use Override and New Keywords - C# Programming Guide | Microsoft Docs[
^]