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

Tengo la clase anterior. ¿Cómo crearías un método para modificarlo?¿Prefiere devolver el objeto modificado o no?

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

o

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

A continuación, llamado así ...

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

o esta

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

¿Cuál es su preferencia?

+0

¿Por qué está pasando la 'Clase x' como parámetro a ModifyIt()? ¿Su método no solo tomará la instancia de Clase como 'esto'? Dado el código que tiene, todas las otras respuestas con respecto al encadenamiento no funcionarán realmente. Para mí, la pregunta sería si su clase tiene más valor, en cuyo caso no debe modificar sus instancias, sino que debe devolver una nueva con el resultado de la operación. – van

Respuesta

2

Lo bueno de hacerlo de la primera manera, en la que en realidad está devolviendo el artículo después de cambiarlo, es que permite el encadenamiento de métodos. Lo que significa que puede hacer algo como esto:

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

Si tiene sentido con su clase específica en la que se puede prever una necesidad para encadenar, y luego volver a la instancia. Si no, entonces puedes dejarlo vacío. Un buen ejemplo de esto es la clase StringBuilder que le permite hacer algo como:

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

"Lo bueno de hacerlo de la segunda [...] manera es que permite el encadenamiento de métodos". Creo que te refieres a la primera manera. Perdón por el comentario, no puedo editar todavía. – PatrikAkerstrand

+0

Vaya, acaba de editar mi publicación, ¡gracias! – BFree

6

Personalmente, prefiero command-query separation - es decir, métodos que devuelven resultados no deben ser mutadores, y viceversa. Entiendo los argumentos a favor de la return this multitud, es decir, la facilidad de "encadenamiento" llama:

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

pero definitivamente no es demasiado malo para codificar esos casos como

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

mientras tanto, las ventajas de " comando-consulta de separación "(en la gran mayoría de los casos, aunque ciertamente no el 100% de ellos), como se discutió en ese wikipeida URL, soportar ...

3

La opción de devolver una instancia del objeto o no dependería en la situación.

Un caso común para la devolución del bien por el método se ve en el builder pattern, tales como la clase StringBuilder:

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

Pero en general, si tales method chaining no se va a realizar, lo elegiría no devolver nada. Si el caso de uso común es no usar el objeto que se devuelve (y simplemente dejarlo caer), lo que parecería ser un desperdicio.

0

En primer lugar, si solo está cambiando una propiedad, no tendría una función de modificación por separado; Solo cambiaría la propiedad directamente. Con eso fuera del camino, supongamos que está dando un ejemplo simple de algo más complicado, con quizás varios cambios diferentes dentro de la función de modificación.

Utilizaría el que devuelve el objeto 'Clase'. Te permite encadenar múltiples llamadas juntas. Nuevamente, asumo que este es un ejemplo simple de un sistema que es realmente más complicado; supongamos que en su lugar tiene MakeModification(), MakeAnotherModification() y MakeAThirdModification().Si devuelve el objeto 'Clase', se puede obtener la siguiente sutileza sintáctica:

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

En realidad, yo prefiero el segundo estilo que el método es un mutador, por lo tanto, no se espera un nuevo valor a devolver, en vez se espera que el valor real sea modificado. Sin embargo, es posible que necesite indicar que ModifyIt acepta una variable de referencia solo para indicar que la c real se modificará. c se pasa por valor, aunque es un tipo de referencia, todavía hay una diferencia entre pasar tipos de referencia por valor y pasar tipos de referencia por ref. Véase el siguiente:

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

en el caso anterior la variable c se pasa por valor (es decir, una copia de la referencia será pasado y modificado para apuntar a un objeto recién instanitiated, que a su vez significa que se tendrá dos objetos de MiClase tipo, en este caso He aquí un ejemplo para ilustrar:.

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

aunque MOdifyIT instanitaited la referenct a un nuevo objeto que debe significar que prob se inicializará a cero, lo que realmente dejase' t instanciar s, instancia una copia de s. a diferencia de la ca se si s pasó por ref.
Espero que esto ayude!

1

Yo personalmente preferiría construir una función como ModifyIt y ponerla en la clase que estoy creando si es posible. La razón por la que digo que es en ambos métodos estoy modificando la variable de llamada porque la estoy pasando por referencia. Naturalmente, no puedo hacer eso para todas las funciones, pero poner ref en la llamada a la función me ayuda a aclarar que estoy pasando una variable por referencia, no pasando una variable por valor. Ejemplo:

public Class ModifyIt(ref Class c) 

¿Por qué? Porque es probable que olvide cuando regrese y lea el código que pasé el valor por referencia, y entonces es más probable que haga algo "malo" con el código.

Cuestiones relacionadas