2008-12-03 7 views
8

Me pregunto cómo otros desarrolladores abordan este problema de obtener 2 o 3 respuestas de un método.Sintaxis de C#: su práctica preferida para obtener 2 o 3 respuestas de un método

1) devuelve un objeto []
2) devuelve una clase personalizada
3) el uso de un cabo o palabra clave ref de múltiples variables
4) escribir o prestado (F #) una tupla sencilla <> clase genérica
http://slideguitarist.blogspot.com/2008/02/whats-f-tuple.html

Estoy trabajando en algún código ahora que actualiza los datos. Desde el método que realiza la actualización me gustaría volver atrás (1) Actualizar hora de inicio y (2) Actualizar hora de finalización.
En una fecha posterior, es posible que desee devolver un tercer valor.

¿Pensamientos? ¿Alguna buena práctica de proyectos de fuente abierta .NET sobre este tema?

+0

Le di el triunfo a Dave R. por la observación de la "firma del método". Parecía saber el problema con el que me iba a encontrar antes de que sucediera. La respuesta de Jon sería # 2. Jon siempre es brillante. – BuddyJoe

Respuesta

5

Su pregunta apunta a la posibilidad de que regrese más datos en el futuro, por lo que le recomendaría implementar su propia clase para contener los datos.

Lo que esto significa es que su firma del método seguirá siendo el mismo incluso si la representación interna del objeto que está pasando alrededor de cambios para dar cabida a más datos. También es una buena práctica para legibilidad y razones de encapsulación.

+0

+1 Buen punto sobre las necesidades futuras. Al usar una clase puede agregar a la clase sin cambiar el método o la persona que llama. – BuddyJoe

10

Para dos, por lo general 4)

Más que eso, 2)

+0

No ayuda aún, pero .NET 4.0 incluirá una clase Tuple genérica en el BCL. –

+0

Suena como una solución típica de Microsoft: agregue otra característica oscura. – dkretz

+1

¿Oscuro? La gente ha estado pidiendo Tuples y valores de retorno múltiples desde la versión 1. –

1

utilizo a cabo si es sólo 1 o 2 variables adicionales (por ejemplo, una función devuelve un bool que es el resultado importante real , pero también un largo como un parámetro de salida para devolver cuánto tiempo funcionó la función, para fines de registro).

Para algo más complicado, normalmente creo una estructura/clase personalizada.

1

Creo que la forma más común en que un programador de C# haría esto sería envolver los elementos que desea devolver en una clase separada. Esto le proporcionaría la mayor flexibilidad en el futuro, en mi humilde opinión.

28

Todo depende de cuáles sean los resultados. Si están relacionados entre sí, normalmente crearía una clase personalizada.

Si no están realmente relacionados, usaría un parámetro out o dividiría el método. Si un método quiere devolver tres elementos no relacionados, probablemente esté haciendo demasiado. La excepción a esto es cuando estás hablando a través de un límite de servicio web u otra cosa donde una API "más pura" puede ser demasiado hablador.

+0

+1 De acuerdo en esto. Los métodos que devuelven> 2 cosas diferentes hacen demasiado – drax

+0

> 1 cosas no relacionadas de todos modos, gran fan de clase E/S para métodos +1 – annakata

+0

99% del tiempo que desea hacer una estructura personalizada, no una clase, pero + 1 de todos modos –

1

Depende. Para una API interna única, generalmente elegiré la opción más fácil. Generalmente eso está fuera.

Para una API pública, una clase personalizada generalmente tiene más sentido, pero si es algo bastante primitivo, o el resultado natural de la función es un booleano (como * .TryParse) me quedaré con un param externo. Puedes hacer una clase personalizada con un elenco implícito para boolear también, pero eso suele ser extraño.

Para su situación particular, una clase de DateRange inmutable simple parece más apropiada para mí. Puede agregar fácilmente ese nuevo valor sin molestar a los usuarios existentes.

2

Código Architeture sabia que siempre iría con una clase personalizada cuando necesita un poco de una cantidad específica de variables modificadas. ¿Por qué? Simplemente porque una clase es en realidad un "modelo" de un tipo de datos de uso frecuente, crear su propio tipo de datos, que en este caso es, lo ayudará a obtener una buena estructura y ayudar a otros a programar su interfaz.

0

Si 2, un par.

Si hay más de 2 en una clase.

+0

Nunca noté la clase System.Web.UI.Pair. Supongo que solo usarías las Tuplas que vienen en VS2010 en el futuro. – BuddyJoe

1

Si tienes intención de devolver las horas de inicio y fin de refresco, que sugiere una posible clase o estructura, tal vez llamados DataRefreshResults. Si su posible tercer valor también está relacionado con la actualización, entonces podría agregarse. Recuerde, una estructura siempre se pasa por valor, por lo que se asigna en el montón no necesita ser recolectada.

2

Personalmente, odio los params/ref params, por lo que prefiero no utilizar ese enfoque. Además, la mayoría de las veces, si necesita devolver más de un resultado, probablemente esté haciendo algo mal.

Si realmente es inevitable, probablemente sea más feliz a la larga escribiendo una clase personalizada. La devolución de una matriz es tentadora, ya que es fácil y efectiva en el corto teerm, pero el uso de una clase le ofrece la opción de cambiar el tipo de devolución en el futuro sin tener que preocuparse demasiado por causar problemas en la secuencia. Imagine el potencial de una pesadilla depuración si alguien intercambia el orden de los dos elementos de la matriz que se devuelve ....

0

Otra solución es devolver un diccionario de referencias a objetos con nombre. Para mí, esto es bastante equivalente a usar una clase de devolución personalizada, pero sin desorden. (Y el uso de RTTI y la reflexión es igual de typesafe como cualquier otra solución, aunque sea de forma dinámica para.)

+0

¡Todo lo que haga en el CLR es dinámicamente seguro, así que eso no significa mucho! –

1

Algunas personas utilizan KeyValuePair para dos valores. Sin embargo, no es genial porque simplemente etiqueta las dos cosas como Key y Value. No muy descriptivo También sería seriamente beneficiarse de tener este añadido:

public static class KeyValuePair 
{ 
    public static KeyValuePair<K, V> Make(K k, V v) 
    { 
     return new KeyValuePair<K, V>(k, v); 
    } 
} 

le evita tener que especificar los tipos cuando se crea uno. Los métodos genéricos pueden inferir tipos, los constructores de clase genéricos no pueden.

1

Para su situación hipotética, es posible que desee definir la clase genérica de rango {T} (con comprobaciones para la validez del rango).

Si el método es privado, entonces generalmente uso tuplas de my helper library. Los métodos públicos o protegidos generalmente siempre se merecen por separado.

1

Devuelva un tipo personalizado, pero no use una clase, use una estructura, sin asignación de memoria/recolección de basura significa que no hay inconvenientes.

0

Depende del tipo y el significado de los resultados, así como de si el método es privado o no.

Para métodos privados, suelo usar un Tuple, de la biblioteca de mi clase.

Para métodos públicos/protegidos/internos (es decir, no privados), utilizo out parameter o una clase personalizada.

Por ejemplo, si estoy poniendo en práctica el patrón TryXYZ, donde se tiene un método XYZ que se produce una excepción en caso de fallo y un método que devuelve TryXYZ de Boole, TryXYZ utilizará un parámetro de salida.

Si los resultados están orientados por secuencia (es decir.devuelvo 3 clientes que deberían procesarse) luego devolveré algún tipo de colección.

Aparte de eso, suelo usar una clase personalizada.

0

Si un método genera dos o tres valores relacionados, los agruparía en un tipo. Si los valores no están relacionados, es muy probable que el método sea demasiado y yo lo refactorizaría en una cantidad de métodos más simples.

Cuestiones relacionadas