2010-03-02 11 views
44

¿Hay algún principio a tener en cuenta al usar los parámetros? ¿O puedo verlos como una buena forma de permitir que un método devuelva múltiples valores?¿Qué es una mala práctica al usar los parámetros?

¿Qué tenían en mente los diseñadores de idiomas cuando especificaban el parámetro out?

Edición después de algún pensamiento:

Como yo estoy pensando en ello ahora, estaría inclinado a decir que el uso excesivo de los parámetros out podría ser indicitive de un código de olor. Si un método necesita devolver instancias de más de 1 tipo específico, implica que el método tiene más de una preocupación, lo cual es una violación de SRP.

+4

Prefiero rodar un objeto personalizado con varias propiedades y devolver eso, luego un montón de variables sueltas, pero eso es solo mi opinión – curtisk

+2

El lugar donde he encontrado parámetros para ser bueno fue xxx.TryParse (out someValue) situaciones, pero estoy interesado en saber más ... – Sunny

+0

pregunta relacionada: http: // stackoverflow.com/questions/413218/best-practice-of-using-the-out-keyword-in-c – ram

Respuesta

30

Personalmente, no estoy demasiado interesado en out parámetros más allá de la establecida TryParse convención. Prefiero devolver una instancia de un tipo específico que encapsula los diferentes parámetros, ya que hace que el código sea mucho más fácil de leer imo.

Si no desea definir tipos específicos para esto, puede usar el tipo Tuple en el próximo .NET framework. Las tuplas son básicamente un grupo de valores envueltos en un tipo. Se usan mucho en, por ejemplo, F#.

+7

Tampoco me gusta mucho TryParse. – recursive

+1

@recursive: Yo tampoco, pero como está en el BCL es difícil de evitar por completo. –

+0

Todavía no he podido encontrar una alternativa fragerente a 'TryParse'. Me encantaría escuchar algunas ideas (¡para objetos personalizados, por supuesto)! –

0

Solo lo mismo que los valores de retorno, es decir. tenga cuidado con todo lo que la clase llamada retendrá y usará más tarde. En general, prefiero un objeto envoltorio; hace que el código de llamada sea un poco más legible.

1

Mientras que out parámetros tienen su uso, antes de usar uno debe parar y pensar si realmente lo necesita. Es posible que pueda obtener una implementación más simple y limpia que no requiera out.

why-are-out-parameters-in-net-a-bad-idea tiene más información.

9

Las herramientas de diseño de clase dicen específicamente para "Avoid out parameters", con una larga discusión de la lógica.

menos que haya una buena razón para usar un parámetro de salida de un método, normalmente es mejor hacer una clase personalizada o estructura para sostener sus resultados. El uso de los parámetros reduce la capacidad de uso de una API.

+0

regla de FXCop "Evitar el parámetro": http: //msdn.microsoft.com/en-us/library/ms182131. aspx – ram

14

El uso de parámetros en general es una mala práctica. Típicamente indica un método que está haciendo más de una cosa bien definida. La única vez que recomiendo usarlos es para los escenarios de Interop, donde a veces son necesarios debido a la firma de la API.

+2

De acuerdo. Si el método devuelve más de un valor ** relacionado **, una clase o una estructura o una matriz probablemente sería una mejor apuesta. Si el método devuelve múltiples valores no relacionados, entonces está haciendo demasiado. – dsimcha

+1

No estoy de acuerdo. Al igual que todas las herramientas 'out' params existen para resolver problemas específicos. El patrón del método 'Try' es un ejemplo de buen uso de parámetros' out'. En este patrón, la bandera devuelta indica si el parámetro de salida fue poblado. Un patrón más complejo es innecesario y simple ofusca las cosas. – 0b101010

+0

Punto justo. Lo que quise decir con "en general" quizás esté mejor indicado como "en la mayoría de los casos". Tienen su lugar, pero ese lugar es limitado en la mayoría del diseño de software diario. – dkackman

2

Utilizo los parámetros cuando escribo métodos estáticos TryParse en mis clases. Solo para mantener la sincronización con el CLR.

Aparte de eso, es probablemente una mejor idea de volver a una clase que tiene lo que necesita en ella.

3

Una advertencia importante a tener en cuenta es que antes de .NET 3.5 SP1, métodos que toman o los tipos de valor de retorno no están inline. Esto podría tener grandes implicaciones de rendimiento para los métodos pequeños y frecuentemente llamados, como los de una biblioteca matemática de vectores.

Ésta es una de las principales razones por las cuales la biblioteca del vector matemáticas SlimDX proporciona sobrecargas que utilizan cabo parámetros en lugar de los valores de retorno; sirve como una potencial micro-optimización.

0

A menudo uso tipos anulables al devolver tipos de valores más un indicador de éxito en lugar de devolver un bool y usar un parámetro out para el tipo de valor. Incluso envuelvo el método TryParse para que devuelva un valor nulo.

Los parámetros de salida son malos también porque deben usar variables locales o campos. No puede refactorizar fácilmente su código para usar propiedades.

Casi siempre es mejor crear una clase/estructura personalizada, usar tuplas o tipos anulables.

1

Generalmente veo los parámetros como un "olor a código", y trataré de refactorizar a un enfoque diferente si me encuentro con ellos. Como alguien ya ha señalado, comúnmente la refactorización será para crear una nueva clase que agregue los valores que iba a devolver a través de params.

1

Hay dos situaciones en las que no veo un problema en absoluto en el uso de out parámetros, y estas situaciones ocurren con mayor frecuencia a lo largo de uno con el otro:

  1. Cuando un método tiene que devolver más de un valor ;
  2. Cuando se usa en métodos privados, específicamente en sub-rutinas imperativas con un nivel de abstracción menor.

Comentarios sobre el motivo:

  • A veces pueden tener las operaciones que cambian más de un estado, por lo que puede funcionar en un grupo de objetos que pertenecen a un mismo proceso con una sola llamada de función (podría ser más semánticamente significativo);
  • Dado que se supone que las variables intraclase tienen una alta cohesión, por lo tanto un alto acoplamiento, creo que "no hace daño" tener métodos que usen los parámetros out. Eso es exactamente lo opuesto para las funciones públicas que espera encontrar en las API;
  • En C#, los parámetros de salida parecen mostrarse mucho en el código derivado de más API de procedimientos portados a OO. Las rutinas numéricas y científicas son el mejor ejemplo que puedo encontrar (alglib, AForge, etc.). Esto refuerza mi idea de que está bien recurrir al out para detalles de implementación interna, que pueden ser muy procesales dependiendo del dominio del problema.

Como un ejemplo de una operación semánticamente "atómica" que cambia dos variables relacionadas pero independientes, aquí va algo de código Python y cómo me portado a C# (en un método privado):

Python:

p1, p2 = FindClosestPair(p, listOfValues) 

C#:

Point3D p1, p2; 
FindClosestPair(p, listOfValues, out p1, out p2); 

no podía pensar en una forma más sencilla de hacerlo (pero yo lov e para conocer posibles alternativas).

Cuestiones relacionadas