tl;dr- Using Child
over Parent
is preferable in the local scope. It not only helps with readability, but it's also necessary to ensure that overloaded method resolution works properly and helps enable efficient compilation.
In the local scope,
Parent obj = new Child(); // Works
Child obj = new Child(); // Better
var obj = new Child(); // Best
Conceptually, it's about maintaining the most type information possible. If we downgrade to Parent
, we're essentially just stripping out type information that could've been useful.
Retaining the complete type information has four main advantages:
- Provides more information to the compiler.
- Provides more information to the reader.
- Cleaner, more standardized code.
- Makes the program logic more mutable.
Advantage 1: More information to the compiler
The apparent type is used in overloaded method resolution and in optimization.
Example: Overloaded method resolution
main()
{
Parent parent = new Child();
foo(parent);
Child child = new Child();
foo(child);
}
foo(Parent arg) { /* ... */ } // More general
foo(Child arg) { /* ... */ } // Case-specific optimizations
In the above example, both foo()
calls work, but in one case, we get the better overloaded method resolution.
Example: Compiler optimization
main()
{
Parent parent = new Child();
var x = parent.Foo();
Child child = new Child();
var y = child .Foo();
}
class Parent
{
virtual int Foo() { return 1; }
}
class Child : Parent
{
sealed override int Foo() { return 2; }
}
In the above example, both .Foo()
calls ultimately call the same override
method that returns 2
. Just, in the first case, there's a virtual method lookup to find the correct method; this virtual method lookup isn't needed in the second case since that method's sealed
.
Credit to @Ben who provided a similar example in his answer.
Advantage 2: More information to the reader
Knowing the exact type, i.e. Child
, provides more information to whoever's reading the code, making it easier to see what the program's doing.
Sure, maybe it doesn't matter to the actual code since both parent.Foo();
and child.Foo();
make sense, but for someone seeing the code for the first time, more information's just plain helpful.
Additionally, depending on your development environment, the IDE may be able to provide more helpful tooltips and metadata about Child
than Parent
.
Advantage 3: Cleaner, more standardized code
Most of the C# code examples that I've seen lately use var
, which is basically shorthand for Child
.
Parent obj = new Child(); // Sub-optimal
Child obj = new Child(); // Optimal, but anti-pattern syntax
var obj = new Child(); // Optimal, clean, patterned syntax "everyone" uses now
Seeing a non-var
declaration statement just looks off; if there's a situational reason for it, awesome, but otherwise it looks anti-pattern.
// Clean:
var foo1 = new Person();
var foo2 = new Job();
var foo3 = new Residence();
// Staggered:
Person foo1 = new Person();
Job foo2 = new Job();
Residence foo3 = new Residence();
Advantage 4: More mutable program logic for prototyping
The first three advantages were the big ones; this one's far more situational.
Still, for people who use code like others use Excel, we're constantly changing our code. Maybe we don't need to call a method unique to Child
in this version of the code, but we might repurpose or rework the code later.
The advantage of a strong type system is that it provides us with certain meta-data about our program logic, making the possibilities more readily apparent. This is incredibly useful in prototyping, so it's best to keep it where possible.
Summary
Using Parent
messes up overloaded method resolution, inhibits some compiler optimizations, removes information from the reader, and makes the code uglier.
Using var
is really the way to go. It's quick, clean, patterned, and helps the compiler and IDE to do their job properly.
Important: This answer is about Parent
vs. Child
in a method's local scope. The issue of Parent
vs. Child
is very different for return types, arguments, and class fields.
Parent x = new Child()
is a good idea.