2009-02-17 8 views
17

¿Cuál es la diferencia entreparámetro del método Modificar dentro de método o retorno resultado

private void DoSomething(int value) { 
    value++; 
} 

y

private int DoSomething(int value) { 
    return value++; 
} 

cuando se utiliza ya sea como

DoSomething(value); 

frente

value = DoSomething(value); 
+3

Para su información, las dos funciones enumeradas son incorrectas. "valor de retorno ++;" devolverá solo el valor, desea "valor de retorno + 1;" o "return ++ value;", y el valor de entrada es solo una copia de la variable pasada a la función a menos que lo designe como un parámetro de referencia con la palabra clave "ref". – Wedge

+0

Este fue un ejemplo excesivamente simplista de mi problema, pero gracias por señalarlo de todos modos. Los métodos en cuestión en mi código están manipulando diccionarios y cadenas. – JMS

Respuesta

32

Usted está hablando de la diferencia entre que pasa por referencia y paso por valor, que es conceptualmente similar a la idea de tipos de valor frente a los tipos de referencia.

Si pasa un valor de ingrese en el método, tiene que usar el segundo ejemplo; de lo contrario, solo está incrementando un entero que existe dentro del alcance de DoSomething(). Pruébalo: si ejecutas tu primer ejemplo, después de ejecutar DoSomething(), el valor de tu int no cambiará.

Sin embargo, si está pasando algo que no sea un tipo de valor (por ejemplo, objeto foo), en realidad está pasando una referencia al objeto original. Cualquier cosa que hagas dentro de DoSomething() tendrá efecto fuera del método también, ya que todavía te estás refiriendo al mismo objeto.

Puede lograr lo que usted está tratando en el primer ejemplo de la escritura:

void DoSomething(ref int value) 

que instruye .NET para pasar una referencia al elemento independientemente de si se trata de un tipo de valor.

Consulte este informe en Value Types vs Reference Types en MSDN para obtener un aspecto más detallado.

Además, como zodoz points out (upvote apropiadamente), al devolver value++ está regresando y luego incrementando. Para devolver el valor incrementado, use ++value.

+2

recuerde que en el 'parámetro hace referencia a un tipo de referencia' caso lo que está haciendo es pasar el * valor * de la referencia. Todavía está pasando por valor. Agregar ref hace que pase genuinamente por referencia (por lo tanto, en lugar de pasar una copia del valor, 'apunta' la función llamada al valor real. – ShuggyCoUk

0

Con la mayoría de los lenguajes de programación, necesitarás cambiar tu función de vacío pasando el parámetro por referencia. Una función por lo general no puede cambiar el valor de sus parámetros; en cambio, crea una copia del parámetro y funciona con eso en su lugar.

el fin de trabajar con la variable real, usted tiene que cambiar la cabecera de la función de aceptar una referencia a la variable, con un signo precedente (&) así:

private void DoSomething(int &value) 

Espero que ayude!

+0

C# usa la palabra clave out, no &. – Ray

+1

En realidad, usted querrá usar ref, no fuera en este caso. –

+1

Buen agarre chicos, soy nuevo aquí y no vi la etiqueta C# .. simplemente se veía como bueno ol 'C++ para mí. – iopener

2

En el primer ejemplo, el parámetro int value se incrementa, pero se destruye cuando termina el método, no se puede obtener el valor fuera del método, a menos que utilice los ref o out palabras clave.

Por ejemplo:

private int DoSomething(ref int value) { 
    return value++; 
} 

// ... 
int myValue = 5; 
DoSomething(ref myValue); 
// Now myValue is 6. 

Ref y fuera modos de paso de parámetros se utilizan para permitir un método para alterar variables pasadas en por la persona que llama método. La principal diferencia entre ref y out puede ser sutil, pero es importante.

Cada modo de paso de parámetros está diseñado para adaptarse a las diferentes necesidades de programación.

La persona que llama de un método que toma un fuera del parámetro no es necesario para asignar a la variable pasada como el parámetro de salida antes de la llamada; sin embargo, se requiere el método para asignar al parámetro de salida antes de regresar.

Una forma de pensar en los parámetros es que son como valores de devolución adicionales de un método. Son convenientes cuando un método debe devolver más de un valor.

El parámetro ref hace que los argumentos se pasen por referencia. El efecto es que cualquier cambio en el parámetro en el método se reflejará en esa variable cuando el control vuelva al método de llamada.

No confunda el concepto de pasar por referencia con el concepto de tipos de referencia.

Los dos conceptos no están relacionados; un parámetro de método puede ser modificado por ref independientemente de si es un tipo de valor o un tipo de referencia, no hay boxeo de un tipo de valor cuando se pasa por referencia.

4

Simplemente el primero no funcionará porque está operando con una copia de valor.

Se podría hacer algo como

private int DoSomething(ref int value) 
{ 
    value++; 
} 

y llamarlo como

DoSomething(ref value); 

Esto cambia el valor de ser aprobada en modo de referencia. Pero realmente la única razón para hacer esto es si desea devolver más de una cosa de su función. Y normalmente hay mejores formas.

Para obtener conocimiento extra adicional, también está la palabra clave out, que es similar a la referencia, pero no requiere que el valor se inicialice primero.

0

Dado que está utilizando postfix ++, el valor devuelto es el valor original del número. Además, dado que está pasando una copia del número y no el número en sí (es decir, por referencia), los cambios realizados en el valor no afectan a la variable que aprobó.

lo tanto un programa como este:

int value=1; 
std::cout<<value<<std::endl; 
value = DoSomething(value); 
std::cout<<value<<std::endl; 

DoSomething(value); 
std::cout<<value<<std::endl; 

salida debe de la siguiente manera:

1 
1 
1 

Si se va a usar el prefijo ++ en el regreso o si tuviera que pasar por referencia en el función de no retorno, el mismo programa generaría la siguiente salida.

1 
2 
3 

Espero que esto ayude.

5

Todo el mundo parece estar sugiriendo la diferencia de paso variable, pero me di cuenta de algo diferente:

Si el código de ejemplo que está visualizando es una simplificación de algo que ya está viendo, entonces puede que desee tener en cuenta que en su segundo ejemplo:

private int DoSomething(int value) { 
    return value++; 
} 

El valuevolverá a continuación incremento. Así que si hace lo siguiente:

public Main() { 
    int val = 1; 
    Console.writeln(DoSomething(val)); 
} 

Su salida será 1.

Avísame si esto ayuda en absoluto.

22

Devuelve un valor.

¿Por qué?

corrección, legibilidad y Auto-Documentación

intencional y fácil de entender el código es mejor que el código de efectos secundarios. Consideremos:

float area = pi * Square(r); 

vs

Square(r); 
float area = pi * r; 
// ... intervening code 
float x = r * 5; // did you mean to use the original r or r-squared here? 

Ten en cuenta también las ventajas de la concisión a través del composability en el primer ejemplo.

Considerar los métodos mismos, comparar:

int DoSomething(int value) 
    { return value+1; } 

que es bastante obvio correcta. contra

void DoSomething(int value) 
    { value++; } 

Lo que parece correcto y se compilará muy bien, pero en realidad es solo una no-op. Lo que realmente quiere es la siguiente:

void DoSomething(ref int value) 
    { value++; } 

// client code: 
DoSomething(ref a); 

Las variables son baratos

Muchas variables bien llamada es preferible sobre algunas variables de propósito general reutilizados. Resista la tentación de optimizar prematuramente, la posibilidad de que necesite reducir el número de variables locales para mejorar el rendimiento de su sistema es cósmicamente pequeña. De nuevo, las variables son baratas, ¡NO REUTILICE LAS VARIABLES!

Comprobabilidad

considerar:

Assert.IsTrue(Square(2) == 4); 

vs.

float a = 2; 
Square(a); 
Assert.IsTrue(a == 4); 

Existen muchas otras ventajas para evitar la mutación antes que devolver un valor. No es simplemente un accidente que las matemáticas definan una función como un mapeo de valores de entrada a valores de salida.

Cuestiones relacionadas