2012-05-13 18 views

Respuesta

4

Tener un argumento en el constructor (constructor no predeterminado), para mí, permite una mejor prueba. Puede 'inyectar' ciertos datos en un campo de miembro que no podría necesariamente hacer sin hacer público ese miembro (o al menos interno) o hacer una segunda llamada con una propiedad 'setter'.

Como puede tener múltiples constructores, podría tener una segunda para probar, junto con un constructor predeterminado, si realmente deseaba.

No hay ningún problema de rendimiento real aparte de tener que realizar una llamada separada para rellenar datos más tarde, o tener un código menos mantenible con múltiples llamadas a la clase (uno para crear el objeto, el segundo para poblar el miembro)

EDIT: Me di cuenta que había respondido una pregunta incorrecta. Pensé que estaba preguntando sobre la diferencia entre los constructores por defecto y los que no lo son. Ahora veo que se trataba de un constructor predeterminado que inicializa el miembro en el constructor frente a la declaración del miembro ...

+0

bien, ¿qué tal el rendimiento y la asignación de memoria? – retide

+1

Esto realmente no tiene sentido. No se puede inyectar algo si no se ofrece como un constructor, y un constructor específico para la prueba es el olor del código (apunta a una clase con demasiadas dependencias directas). Si realmente desea desacoplar la clase, tome todos los parámetros que puedan necesitar ser cambiados como interfaces. – Femaref

+0

Quizás, pero en el contexto de su pregunta con esta variable miembro, ciertamente es una opción. Acepto, en caso de que tenga muchas propiedades, cree una interfaz y póngala. – Killnine

1

Los dos son equivalentes. El compilador mueve la inicialización de dichos miembros al constructor (constructor estático si el miembro es estático). No diría que hay una mejor manera general de hacerlo, simplemente sea consistente siempre que sea posible, y si tiene más sentido en la situación, úselo.

1

Inicializa los miembros de la instancia en el constructor, inicializa los miembros de la clase en la declaración. AFAIK esta es (solo) la convención, y no hay penalización de rendimiento. En mi humilde opinión esto debería ser forzado a la regla del lenguaje (sintaxis/semántica).

10

Son prácticamente equivalentes (las diferencias en términos de rendimiento y uso de la memoria son insignificantes). La única diferencia real es que cuando lo hace:

private List<string>name = new List<string>(); 

... la asignación siempre sucede, no importa lo que el constructor se utiliza para crear una instancia del objeto. Cuando haces la tarea dentro de un constructor, solo ocurre cuando se usa ese constructor específico.

Si tiene varios constructores pero siempre quiere inicializar name exactamente de la misma manera, es un poco más corto usar el primer formulario que inicializarlo explícitamente en cada constructor.

Como regla general, sin embargo, prefiero inicializar campos en las implementaciones de constructores, incluso si hace que el código sea más detallado en algunos casos.

+0

Como nota al margen, el compilador realmente mueve cualquier código de inicialización de miembros a todos los constructores. Esto significa que no debe haber absolutamente ninguna diferencia de requisitos de rendimiento/uso de memoria al ponerlo usted mismo en el constructor, excepto que las instrucciones se repetirán para cada constructor en uso (esto solo sería significativo si tiene megabytes de instrucciones de inicialización para miembros de instancia) declarado de esta manera, y múltiples constructores). –

+0

Esta es una muy buena explicación, y en realidad responde a la pregunta;) +1 – Killnine

+0

@TimS. ¿Tiene alguna evidencia para respaldar la afirmación de que los inicializadores de campo se mueven a los constructores? Me parece muy poco probable, ya que [los inicializadores de campo y los constructores de las clases base no se invocan en el mismo orden] (http://blogs.msdn.com/b/ericlippert/archive/2008/02/15/why-do -inicializadores-run-in-the-opposite-order-as-constructors-part-one.aspx). El inicializador de campo ejecuta * antes de * los inicializadores de campo de la clase base, y antes de su constructor; el constructor ejecuta * después de * el constructor de la clase base. – phoog

1

campos Inicialización en el constructor también le permite evitar este problema:

class MyClass 
{ 
    private List<string> _list = new List<string>(); 
    public MyClass() 
    { 
     //some logic here 
    } 
    public MyClass(List<string> initialList) : this() 
    { 
     _list = initialList; 
    } 
} 

Con este código, si se llama al segundo constructor, va a crear innecesariamente una lista que se abandonó casi inmediatamente e hizo elegible para recolección de basura.

Cuestiones relacionadas