tl; dr : es preferible utilizarChild
overParent
en el ámbito local. No solo ayuda con la legibilidad, sino que también es necesario garantizar que la resolución del método sobrecargado funcione correctamente y ayuda a permitir una compilación eficiente.
En el ámbito local,
Parent obj = new Child(); // Works
Child obj = new Child(); // Better
var obj = new Child(); // Best
Conceptualmente, se trata de mantener la mayor cantidad de información posible. Si bajamos a Parent
, esencialmente estamos eliminando información de tipo que podría haber sido útil.
Retener la información de tipo completa tiene cuatro ventajas principales:
- Proporciona más información al compilador.
- Proporciona más información al lector.
- Código más limpio y estandarizado.
- Hace que la lógica del programa sea más mutable.
Ventaja 1: más información para el compilador
El tipo aparente se usa en la resolución de métodos sobrecargados y en la optimización.
Ejemplo: resolución de método sobrecargado
main()
{
Parent parent = new Child();
foo(parent);
Child child = new Child();
foo(child);
}
foo(Parent arg) { /* ... */ } // More general
foo(Child arg) { /* ... */ } // Case-specific optimizations
En el ejemplo anterior, ambas foo()
llamadas funcionan , pero en un caso, obtenemos la mejor resolución del método sobrecargado.
Ejemplo: optimización del compilador
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; }
}
En el ejemplo anterior, ambas .Foo()
llamadas finalmente llaman al mismo override
método que devuelve 2
. Simplemente, en el primer caso, hay una búsqueda de método virtual para encontrar el método correcto; esta búsqueda de método virtual no es necesaria en el segundo caso, ya que la de ese método sealed
.
Gracias a @Ben, quien proporcionó un ejemplo similar en su respuesta .
Ventaja 2: más información para el lector
Conocer el tipo exacto, es decir Child
, proporciona más información a quien lea el código, lo que facilita ver lo que está haciendo el programa.
Claro, tal vez no importa que el código real, ya que ambos parent.Foo();
, y child.Foo();
tiene sentido, pero para alguien ver el código por primera vez, más información es simplemente útil.
Además, dependiendo de su entorno de desarrollo, el IDE puede ser capaz de proporcionar información sobre herramientas más útiles y metadatos acerca Child
de Parent
.
Ventaja 3: código más limpio y estandarizado
La mayoría de los ejemplos de código C # que he visto últimamente usan var
, que es básicamente una forma abreviada de 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
Ver una var
declaración de no declaración simplemente se ve mal; si hay una razón situacional para ello, increíble, pero de lo contrario parece antipatrón.
// 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();
Ventaja 4: lógica de programa más mutable para la creación de prototipos
Las tres primeras ventajas fueron las grandes; este es mucho más situacional.
Aún así, para las personas que usan código como otros usan Excel, estamos cambiando constantemente nuestro código. Tal vez no es necesario llamar a un método único para Child
en esta versión del código, pero que podríamos reutilizar o reelaborar el código más tarde.
La ventaja de un sistema de tipo fuerte es que nos proporciona ciertos metadatos sobre la lógica de nuestro programa, lo que hace que las posibilidades sean más evidentes. Esto es increíblemente útil en la creación de prototipos, por lo que es mejor mantenerlo donde sea posible.
Resumen
El uso Parent
desordenado de la resolución del método sobrecargado, inhibe algunas optimizaciones del compilador, elimina la información del lector y hace que el código sea más feo.
Usar var
es realmente el camino a seguir. Es rápido, limpio, está diseñado y ayuda al compilador y al IDE a hacer su trabajo correctamente.
Importante : Esta respuesta es sobreParent
vs.Child
en el ámbito local de un método. El problema deParent
vs.Child
es muy diferente para los tipos de retorno, argumentos y campos de clase.