2010-06-30 12 views
27

C# in VS2005: se una classe ha due costruttori, qual è il modo migliore per questi costruttori di condividere del codice?C#: se una classe ha due costruttori, qual è il modo migliore per questi costruttori di condividere del codice?

es. Come avrei potuto evitare di avere le x = 5 e y = 10 linee in entrambi i costruttori per la seguente:

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; 
} 

risposta

51

Proprio catena al costruttore comune ...

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

Ciò causerà l'esecuzione del costruttore base se la classe è ereditata? – CJ7

+0

@ CJ7 Sì. Il costruttore della classe base/catena principale è/viene sempre eseguito prima che venga eseguito il costruttore della classe corrente. Puoi leggere di più [qui] (https://stackoverflow.com/q/9171629/465053). Il thread – RBT

+0

[Questo] (https://stackoverflow.com/q/1882692/465053) contiene ulteriori informazioni sul concatenamento del costruttore. – RBT

7

usare la sintassi this().

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

cosa se la classe è ereditata? Questo() chiamerà anche il costruttore di base? – CJ7

+0

'MyObject()' chiama implicitamente il costruttore parametrico di base. –

+0

@Craig, 'base()' verrà chiamato implicitamente se non lo si fa direttamente. La classe base verrà costruita prima della classe derivata, indipendentemente dal nome del costruttore derivato. –

5

Creare un altro metodo:

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

Poi hanno entrambe le versioni della vostra chiamata al costruttore di questo metodo:

public MyObject() { 
    setDefaultNumbers(); 
} 

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

Lo raccomanderei solo se setDefaultNumbers è qualcosa che potresti vedere chiamare dopo che l'oggetto è stato creato. Anche se è privato, non c'è modo di contrassegnarlo come 'solo per costruttori' a meno che non sia solo nei costruttori. Se puoi, preferirei i costruttori concatenati, a meno che non ci sia modo di ricollegarli in modo pulito. – Dolphin

+1

FYI, ci sono due vantaggi dell'utilizzo di una routine di installazione su una chiamata del costruttore nidificata: (1) Il costruttore esterno può eseguire codice arbitrario prima della routine di configurazione comune; (2) La routine di installazione può essere racchiusa in un blocco try/finally per garantire che qualsiasi oggetto IDisposable creato prima dell'esecuzione della routine di installazione venga ripulito se la routine di installazione genera un'eccezione. In alcuni casi, può essere utile per una classe base estendibile avere tutti i suoi costruttori pubblici che chiamano una routine di installazione protetta, ma avere un costruttore protetto che non lo fa. I costruttori di classi derivati ​​potrebbero ... – supercat

+0

... chiamare il costruttore protetto e quindi chiamare la routine di installazione. Ovviamente questo modello richiederebbe un po 'di attenzione, ma in scenari in cui la classe derivata ha bisogno di creare alcuni oggetti IDisposabili e passarli al "costruttore" interno è probabilmente lo schema più sicuro. Nota che chiamare base.new (new SomeDisposableType) è un modello pericoloso che non può essere reso sicuro se c'è qualche possibilità che base.new potrebbe lanciare. – supercat

3

È molto simile al w lo faresti con i metodi. Normalmente si dovrebbe fare qualcosa di simile:

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

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

con i costruttori, non c'è sintassi speciale per esso:

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

public void MyObject(int b) 
    : this() 
{ 
    this.b = 10; 
} 
Problemi correlati