2009-04-14 33 views
8

Digamos por un momento que C# permite múltiples valores de retorno en el sentido más puro, donde esperaríamos ver algo como:C# - Azúcar sintáctico para los parámetros de salida?

string sender = message.GetSender(); 
string receiver = message.GetReceiver(); 

compactado a:

string sender, receiver = message.GetParticipants(); 

En ese caso, No tengo que entender los valores de retorno del método hasta que realizo la llamada al método. Tal vez confío en Intellisense para decirme a qué valor (s) de retorno me refiero, o tal vez estoy buscando un método que devuelva lo que quiero de una clase con la que no estoy familiarizado.

Del mismo modo, tenemos algo como esto, en la actualidad, en C#:

string receiver; 
string sender = message.GetParticipants(out receiver); 

donde el argumento a GetParticipants es un parámetro cabo cadena. Sin embargo, esto es un poco diferente al anterior porque significa que debo anticiparme con, o al menos volver atrás y escribir, el código que crea una variable para contener el resultado del parámetro out. Esto es un poco contrario a la intuición.

Mi pregunta es, ¿hay algún azúcar sintáctico en la corriente C#, que permita a un desarrollador hacer esta declaración en la misma línea que la llamada al método? Creo que sería hacer que el desarrollo de una (pequeña) poco más de líquido, y también hacer el código más legible si estuviera haciendo algo como:

string sender = message.GetParicipants(out string receiver); 

para demostrar que el receptor estaba siendo declarada y asignada en el acto.

+0

Su ejemplo actual de C# también debería agregar el modificador "out" al * argumento *: string sender = message.GetParticipants (out receiver); –

+0

edite los GetParicipants, no tengo derecho a hacerlo –

+0

Esto ha sido [sugerido como una posible característica para C# 6.0] (http://damieng.com/blog/2013/12/09/probable-c-6- 0-features-illustrated). –

Respuesta

9

No, actualmente no hay ningún azúcar sintáctico alrededor de esto. No he oído ninguna intención de presentar ninguno tampoco.

No puedo decir que utilizo los parámetros out con la frecuencia suficiente para que realmente sea una preocupación importante para mí (hay otras características en las que preferiría que el equipo C# pasara su tiempo) pero estoy de acuerdo que es un poco molesto.

+0

¿Cómo es la implementación actual un doble estándar ...? –

+0

Como no son valores devueltos, están fuera de los parámetros. No hay un "doble estándar": son cosas diferentes, tratadas de manera diferente. No es como si representara el valor de retorno como un parámetro de salida inicial o algo así: en * ese * punto sería justo llamarlo de doble estándar. –

+0

Tenga en cuenta que los parámetros * no son * iguales a los valores de retorno de todos modos. Puede asignar el valor de un parámetro de salida durante el método, y ese cambio ocurre inmediatamente. Puede ver esto si llama a un método y usa una variable de instancia para el argumento out. –

0

En el mejor de los casos tendría que usar var en lugar de un tipo explícito, a menos que desee restringir todos los valores de retorno múltiples para que sean del mismo tipo (no es práctico). También estaría limitando el alcance de la variable; actualmente puede declarar una variable en un alcance mayor e inicializarla en un parámetro out. Con este enfoque, la variable saldría del alcance en el mismo bloque que su asignación. Obviamente, esto se puede usar en algunos casos, pero no quisiera aplicar esto como regla general. Obviamente, podría dejar la opción 'out' en su lugar, pero es probable que las personas codifiquen para un enfoque u otro.

+0

Tener que usar var no es verdadero, el azúcar sintáctico, si existiera, debería simplemente declarar una nueva variable en el mismo ámbito que usted mencionó, y pasarla al método de asignación. Por lo tanto, cada parámetro se escribiría de forma natural. – JoshJordan

+0

cadena param1, int param2 = FuncCall (param3)? –

+0

El mensaje preguntaba sobre el azúcar sintáctico de la forma: cadena devuelta = FuncCall (out int param2, out string param3). Sin embargo, lo que ha publicado sería una forma viable, sí. – JoshJordan

-1

Prueba el siguiente código

Participants p = message.GetParticipants(); 
log(p.sender,p.receiver); 
-1

creo que esto no es lo que quiere. Es posible que haya encontrado un fragmento de código en el que le hubiera gustado . Pero las variables que hacen estallar de la nada, porque que han sido introducidos en la lista de parámetros serían una pesadilla personal (para mí :))

valores de retorno múltiples tienen inconvenientes graves desde el punto de la portabilidad/mantenibilidad. Si realiza una función que devuelve dos cadenas y ahora desea que devuelva tres, tendrá que cambiar todo el código que utiliza esta función. Un tipo de registro devuelto, sin embargo, generalmente funciona bien en tales escenarios comunes.

que puede abrir la caja de pandora ;-)

para la compactación de la línea:

string s1, s2; s1 = foo.bar(s2); 

líneas pueden ser cualquier longitud, por lo que podría empacar algunas cosas comunes en una sola. Solo trata de vivir con el punto y coma.

+1

No lo compacte ... – Jabe

+0

Bueno, hay muchos, muchos constructos que tienen graves implicaciones para la facilidad de mantenimiento, y los desarrolladores deben aprender a trabajar con ellos. En este caso, sería más probable que no sea apropiado introducir otro método del mismo nombre pero con una firma de devolución diferente. – JoshJordan

+0

El punto es que las variables "que salen de la nada" es lo que tenemos para un único valor de retorno, si elegimos hacer una declaración y una tarea. La falta de una facilidad para hacer esto para múltiples valores de retorno (o params) nos da un doble estándar. – JoshJordan

5

.NET 4 agregará un concepto Tuple, que se ocupa de esto. Desafortunadamente, el lenguaje C# no proporcionará ningún soporte de idioma para "enlazar desestructurado".

+2

Se llama "enlace desestructurado". –

2

También puede devolver Tuple<T,U> o algo similar. Sin embargo, dado que desea devolver dos cadenas, puede ser confuso.

Utilizo las estructuras Tuples del BclExtras library que es muy útil (lo encontré en SO, gracias JaredPar!).

4

Personalmente, me gusta la inconveniencia que se presenta al usar los parámetros. Me ayuda a pensar si mi método realmente está haciendo lo que debería o si he acumulado demasiada funcionalidad en él. Dicho esto, tal vez escribir dinámicamente en C# 4.0/.Net 4 abordará algunas de sus preocupaciones.

dynamic participant = message.GetParticipants(); 

var sender = participant.Sender; 
var recipient = participant.Recipient; 

donde

public object GetParticipants() 
{ 
    return new { Sender = ..., Recipient = ... }; 
} 
+0

¡Puaj, parece tan feo! –

2

No creo que exista tal funcionalidad, pero si se llevaron a cabo de una manera similar a las matrices en Perl que podrían ser útiles en realidad.

En perl Puede asignar una matriz a una lista de variables entre paréntesis. Así puede por ejemplo hacer esto

 
($user, $password) = split(/:/,$data); 
2

Cuando esto me molesta más: ya que no hay sobrecarga de (digamos) DateTime.TryParse que no toma un parámetro out, no se puede escribir

if (DateTime.TryParse(s, out d)) 
{ 
    return new ValidationError("{0} isn't a valid date", s); 
} 

sin declarar d. No sé si esto es un problema con los parámetros out o simplemente con cómo se implementa el método TryParse, pero es molesto.

Cuestiones relacionadas