2009-06-03 2 views
5
Class c = new Class({ Prop = "Initial" }); 

Ho la classe sopra. Come creeresti un metodo per modificarlo?Preferisci restituire l'oggetto modificato o no?

public Class ModifyIt(Class c) 
{ 
    c.Prop = "changed"; 
    return c; 
} 

o

public void ModifyIt(Class c) 
{ 
    c.Prop = "changed"; 
} 

Allora si chiamava così ...

Class c = ModifyIt(c); 
Console.WriteLine(c.Prop); 
// changed 

o questo

ModifyIt(c) 
Console.WriteLine(c.Prop); 
// changed 

Che cosa è la vostra preferenza?

+0

Perché stai passando la "Classe x" come parametro a ModifyIt()? Il tuo metodo non prenderà semplicemente l'istanza di Class come 'this'? Dato il codice che hai tutte le altre risposte riguardanti il ​​concatenamento non funzionerà davvero. Per me la domanda sarebbe se la tua classe fosse più di un tipo di valore, nel qual caso non dovresti modificare le tue istanze, ma piuttosto restituirne una nuova con il risultato dell'operazione. – van

risposta

2

La cosa interessante di farlo nel modo in cui in effetti si restituisce l'oggetto dopo averlo modificato, è che consente il concatenamento del metodo. Significa che è possibile fare qualcosa di simile:

c.ModifyIt("hello").MessWithIt("World").ReallyScrewWithIt("!!!"); 

Se ha senso con la vostra specifica classe in cui è possibile prevedere la necessità di concatenamento, per poi tornare l'istanza. Se no, allora puoi solo renderlo vuoto. Un buon esempio di questo è la classe StringBuilder, che ti permette di fare qualcosa di simile:

myStringBuilder.Replace("!", "?").Append("Something").Remove(4,3); 
+0

"Il bello di farlo al secondo modo [...] è che consente il concatenamento del metodo". Penso che tu intenda la prima strada. Ci scusiamo per il commento, non possiamo ancora modificare. – PatrikAkerstrand

+0

Oops, ho appena modificato il mio post, grazie! – BFree

6

Personalmente, preferisco command-query separation - vale a dire, i metodi di restituire un risultato non dovrebbe essere mutatori, e viceversa. Capisco gli argomenti per la return this folla, vale a dire, la facilità di "concatenamento" chiama:

foo.ChangeThis(23).ChangeThat(45).AndAlso(67); 

ma non è decisamente troppo brutto per codificare i casi come

var x=foo; 
x.ChangeThis(23); x.ChangeThat(45); x.AndAlso(67); 

Nel frattempo, i vantaggi del " comando-query separazione "(nella stragrande maggioranza dei casi, anche se certamente non il 100% di essi), come discusso in quell'URL di wikipeida, resistere ...

3

La scelta di restituire un'istanza dell'oggetto o non dipenderebbe sulla situazione

Un caso comune per il ritorno l'oggetto con il metodo è visto nel builder pattern, come la classe StringBuilder:

new StringBuilder("Hello").Append(" ").Append("World!").ToString(); 

Ma, in generale, se tale method chaining non sta per essere eseguito, ho sceglierei di non restituire nulla. Se il caso d'uso comune è di non usare l'oggetto che viene restituito (e lo si fa semplicemente cadere), che sembrerebbe essere uno spreco.

0

Prima di tutto, se si sta cambiando solo una proprietà, non avrei affatto una funzione di modifica separata; Vorrei semplicemente cambiare la proprietà direttamente. Con quello fuori mano, assumiamo che stai dando un semplice esempio di qualcosa di più complicato, con forse diverse modifiche all'interno della funzione di modifica.

Vorrei usare quello che restituisce l'oggetto 'Classe'. Ti consente di collegare più chiamate contemporaneamente. Di nuovo, presumo che questo sia un semplice esempio di un sistema che è in realtà più complicato; supponiamo invece di avere MakeModification(), MakeAnotherModification() e MakeAThirdModification().Se si restituisce l'oggetto 'Classe', è possibile ottenere i seguenti delicatezza sintattica:

Class c = new Class(); 
c.MakeModification().MakeAnotherModification().MakeAThirdModification(); 
0

In realtà io preferisco il secondo stile come il metodo è un mutatore, quindi, un nuovo valore non dovrebbe essere restituito, invece il valore effettivo dovrebbe essere modificato. Tuttavia potrebbe essere necessario indicare che ModifyIt accetta una variabile ref solo per indicare che la c effettiva sarà modificata. c qui viene passato per valore, anche se è un tipo di riferimento, c'è ancora una differenza tra il passaggio dei tipi di riferimento per valore e il passaggio dei tipi di riferimento mediante ref. Vedere la seguente:

public void ModifyIt(Myclass c) { c = new MyClass(); } 

nel caso precedente la variabile c viene passato per valore (ossia una copia dal riferimento sarà passata e modificata per puntare a un oggetto appena instanitiated, che a sua volta significa che avrà due oggetti di tipo MyClass in questo caso Ecco un esempio per illustrare:.

Myclass s = new MyClass() { prop = "value" }; ModifyIt(s); Console.WriteLine(s.prob); // this will print "value" 

se MOdifyIT instanitaited il referenct a un nuovo oggetto che deve significare che prob viene inizializzata a zero, in realtà didn' t istanziato s, ha istanziato una copia di s, a differenza del ca se se s è stato superato da ref.
Spero che questo aiuti!

1

Personalmente preferirei creare una funzione come ModifyIt e inserirla nella classe che sto creando, se possibile. La ragione per cui dico che è in entrambi i metodi sto modificando la variabile chiamante perché la sto passando per riferimento. Naturalmente, non posso farlo per tutte le funzioni, ma inserire la funzione nella chiamata aiuta a chiarire che sto passando una variabile per riferimento, non passando una variabile per valore. Esempio:

public Class ModifyIt(ref Class c) 

Perché? Perché sono suscettibile di dimenticare quando torno e leggere il codice che ho passato il valore per riferimento e sono quindi più probabile fare qualcosa di "cattivo" per il codice.