2011-03-11 17 views
9

tengo la clase siguiente:Pase por referencia: ¿Cuál es más legible/correcto?

public class Person 
{ 
    public String Name { get; set; } 
} 

Tengo un método que toma en Person y una String como parámetros:

public void ChangeName(Person p, String name) 
{ 
    p.Name = name; 
} 

Desde Person se hizo pasar por referencia, se debe cambiar el Name de la instancia aprobada

¿Pero es este método más legible que el anterior?

public Person ChangeName(Person p, String name) 
{ 
    p.Name = name; 
    return p; 
} 
+1

Técnicamente, 'p 'no se pasa por referencia en cualquiera de esos ejemplos. – Amber

+0

@Amber ¿Qué tal? Estoy bastante seguro de que es completamente incorrecto. –

+3

'p' * contiene * y * pasa * una referencia, pero no * pasado por referencia * - hay una diferencia clara entre los dos. Pase por referencia (al declarar los argumentos como 'ChangeName (ref Person p, ...)' permitiría algo como 'p = foo' para luego cambiar completamente a qué Persona apuntaba la variable de la persona que llama, no solo los contenidos de la actual Persona señalada. – Amber

Respuesta

12

¿Es más legible? No. De hecho, es posible que les estés haciendo más daño.

Al hacer que devuelva un objeto Person, podría hacerle creer que en lugar de modificar el parámetro Person, en realidad está creando una nueva Persona basada en p pero con un nombre diferente y alguien podría asumir incorrectamente que p nunca cambiado

De cualquier manera, si tiene un método que no tiene ningún efecto en la clase que es aparte de él, probablemente debería ser estático. Eso lo ayuda a estar seguro de que no afecta su clase. Solo haga que el método devuelva un valor si lo necesita para devolver un valor.

Así que aquí es mi recomendación para este método:

public static void ChangeName(Person p, String name) 
{ 
    p.Name = name; 
} 
0

En el caso que usted ha descrito, yo diría que no. No está muy claro qué estás tratando de hacer con este método. Solo usa el objeto y establece la propiedad. Insertar un método en la ruta de ejecución simplemente complica la comprensión y crea otra dependencia en el objeto Persona y su valor subyacente.

Si está haciendo una meta pregunta que implica algún diseño más allá del código que ha publicado, entonces me lo estoy perdiendo.

0

El primero es mejor, por eso el segundo puede llevarte a creer que p es inmutable. Pero, todo el método es inútil ya que solo llama al colocador. ¿Por qué no simplemente llamar al colocador directamente?

1

No hay nada de correcto/incorrecto con cualquier enfoque. Depende de lo que su programa necesita.

La devolución del parámetro pasado a un método rara vez se necesita, ya que siempre es posible que el usuario simplemente use la variable pasada como argumento en su lugar.

Sin embargo, le da la flexibilidad de eventualmente anular esta implementación, o pasar esta implementación a otra función que acepte delegados con firmas similares. Luego puede pasar otras implementaciones que no devuelven el mismo objeto Person.

Hazlo solo si realmente necesitas la flexibilidad.

1

Yo sugeriría que utilice uno de los siguientes para una mejor legibilidad:

public static void ChangeName(Person p, String name) 
{ 
    p.Name = name; 
} 

public static Person WithName(Person p, String name) 
{ 
    return new Person(p) { Name = name };  
} 

La segunda trata el objeto Persona como inmutable y no cambia el estado del objeto. La función ChangeName cambia explícitamente el estado del objeto de entrada.Creo que es importante hacer una distinción clara entre los dos tipos de métodos. Una buena regla a seguir es que un método no debe cambiar el estado de un objeto Y devolver uno al mismo tiempo.

0

Creo que su segundo enfoque no es más legible YAGNI. Pero si lo cambia como esto

public static class PersonExtensions 
{ 
public static Person ChangeName(this Person p, String name) 
{ 
p.Name = name; 
return p; 
} 

tendrá una extensionmethod para una interfaz fluidaa la que no se está pasando

new Person().ChangeName("Peter Smith").SendEmail().Subject("Test Mail").Receiver("....) 
1

en primer lugar p por referencia en el primer ejemplo . Su segundo método hace creer que está devolviendo una nueva referencia que no es. Entonces, no creo que el segundo sea más claro que el primero.

0

Here es la referencia definitiva para comprender el paso de parámetros por valor/referencia.

Al observar el código, ¿por qué no utiliza la propiedad?

public string Name 
{ 
    set {name = value;} 
    get { return name; } 
} 

EDIT: Auto implemented properties

public string Name 
{ 
    set; 
    get; 
} 
Cuestiones relacionadas