2010-06-30 8 views
27

C# en VS2005: si una clase tiene dos constructores, ¿cuál es la mejor forma para que estos constructores compartan algún código?C#: si una clase tiene dos constructores, ¿cuál es la mejor forma para que estos constructores compartan algún código?

por ejemplo. ¿Cómo podría evitar que las x = 5 y y = 10 líneas en los dos constructores para lo siguiente:

public class MyObject { 

int x; 
int y; 
int z; 

public MyObject() { 
    x = 5; 
    y = 10; 
} 

public MyObject(int setZ) { 
    x = 5; 
    y = 10; 
    z = setZ; 
} 

Respuesta

51

cadena Sólo al constructor común ...

public MyObject(int setZ) 
    : this() 
{ 
    z = setZ; 
} 
+4

¿Esto causará que el constructor base se ejecute si la clase es heredada? – CJ7

+0

@ CJ7 Sí. El constructor de la clase base/cadena padre siempre se ejecuta primero antes de que se ejecute el constructor de la clase actual. Puede leer más sobre esto [aquí] (https://stackoverflow.com/q/9171629/465053). – RBT

+0

[Este] (https://stackoverflow.com/q/1882692/465053) thread tiene más información sobre el encadenamiento de constructores. – RBT

7

utilizar la sintaxis this().

public MyObject(int setZ) : this() { 
    z = setZ; 
} 
+0

lo que si se hereda de la clase? ¿Esto() llamará al constructor base también? – CJ7

+0

'MyObject()' invoca implícitamente el constructor sin parámetros base. –

+0

@Craig, 'base()' se invocará implícitamente si no lo hace directamente. La clase base se construirá antes que la clase derivada sin importar a qué constructor derivado se llame. –

5

Crear otro método:

private setDefaultNumbers() { 
    x = 5; 
    y = 10; 
} 

Entonces tienen dos versiones de su llamada al constructor este método:

public MyObject() { 
    setDefaultNumbers(); 
} 

public MyObject(int setZ) { 
    setDefaultNumbers(); 
    z = setZ; 
} 
+0

Solo recomendaría esto si setDefaultNumbers es algo que pueda ver llamando después de que se crea el objeto. Incluso si es privado, no hay forma de marcarlo como 'solo para constructores' a menos que solo esté en los constructores. Si puede, preferiría los constructores encadenados, a menos que no haya forma de encadenarlos limpiamente. – Dolphin

+1

Para su información, hay dos ventajas de usar una rutina de configuración sobre una llamada de constructor anidada: (1) El constructor externo puede ejecutar código arbitrario antes de la rutina de configuración común; (2) La rutina de configuración puede envolverse en un bloque try/finally para garantizar que cualquier objeto IDisposable creado antes de que se ejecute la rutina de instalación se limpiará si la rutina de configuración arroja una excepción. En algunos casos, puede ser útil que una clase base extensible tenga todos sus constructores públicos para llamar a una rutina de configuración protegida, pero tenga un constructor protegido que no lo haga. Los constructores de clases derivadas podrían ... – supercat

+0

... llamar al constructor protegido y luego llamar a la rutina de configuración ellos mismos. Obviamente, este patrón requerirá cierto cuidado, pero en escenarios donde la clase derivada necesita crear algunos objetos IDisposables y pasarlos al "constructor" interno, es probablemente el patrón más seguro. Tenga en cuenta que llamar a base.new (nuevo SomeDisposableType) es un patrón peligroso que no se puede proteger si hay alguna posibilidad de que base.new pueda lanzar. – supercat

3

Es muy similar a la w ay lo harías con métodos. Lo normal es que hacer algo como:

public void SetA(int a) 
{ 
    this.a = a; 
} 

public void SetAandB(int a, int b) 
{ 
    this.SetA(a); 
    this.b = b; 
} 

con los constructores, hay una sintaxis especial para ella:

public void MyObject() 
{ 
    this.a = 5; 
} 

public void MyObject(int b) 
    : this() 
{ 
    this.b = 10; 
} 
Cuestiones relacionadas