tuple dotnetperls create c# struct tuples out value-type

dotnetperls - tuple create c#



Devolviendo dos valores, Tuple vs ''out'' vs ''struct'' (6)

Considere una función que devuelve dos valores. Podemos escribir:

// Using out: string MyFunction(string input, out int count) // Using Tuple class: Tuple<string, int> MyFunction(string input) // Using struct: MyStruct MyFunction(string input)

¿Cuál es la mejor práctica y por qué?


Agregando a las respuestas anteriores, C # 7 trae tuplas de tipo de valor, a diferencia de System.Tuple que es un tipo de referencia y también ofrece una semántica mejorada.

Aún puede dejarlos sin nombre y usar la sintaxis .Item* :

(string, string, int) getPerson() { return ("John", "Doe", 42); } var person = getPerson(); person.Item1; //John person.Item2; //Doe person.Item3; //42

Pero lo realmente poderoso de esta nueva característica es la capacidad de tener tuplas con nombre. Entonces podríamos reescribir lo anterior así:

(string FirstName, string LastName, int Age) getPerson() { return ("John", "Doe", 42); } var person = getPerson(); person.FirstName; //John person.LastName; //Doe person.Age; //42

La desestructuración también es compatible:

(string firstName, string lastName, int age) = getPerson()


Cada uno tiene sus pros y sus contras.

Los parámetros de salida son rápidos y baratos, pero requieren que pase una variable y confíe en la mutación. Es casi imposible usar correctamente un parámetro de salida con LINQ.

Las tuplas ejercen presión sobre la recopilación y no se documentan por sí mismas. "Item1" no es muy descriptivo.

Las estructuras personalizadas pueden ser lentas para copiar si son grandes, pero son autodocumentadas y eficientes si son pequeñas. Sin embargo, también es un dolor definir un conjunto completo de estructuras personalizadas para usos triviales.

Me inclinaría a la solución de estructura personalizada en igualdad de condiciones. Aún mejor es hacer una función que solo devuelva un valor . ¿Por qué estás devolviendo dos valores en primer lugar?

ACTUALIZACIÓN: tenga en cuenta que las tuplas en C # 7, que se enviaron seis años después de la redacción de este artículo, son tipos de valores y, por lo tanto, es menos probable que creen una presión de recopilación.


Creo que la respuesta depende de la semántica de lo que está haciendo la función y la relación entre los dos valores.

Por ejemplo, los métodos TryParse toman un parámetro de out para aceptar el valor analizado y devuelven un bool para indicar si el análisis se realizó TryParse o no. Los dos valores en realidad no pertenecen juntos, así que, semánticamente, tiene más sentido, y la intención del código es más fácil de leer, para usar el parámetro out .

Sin embargo, si su función devuelve las coordenadas X / Y de algún objeto en la pantalla, entonces los dos valores se unen semánticamente y sería mejor usar una struct .

Yo personalmente evitaría usar una tuple para cualquier cosa que sea visible para el código externo debido a la sintaxis incómoda para recuperar los miembros.


Iré con el enfoque de usar el parámetro Out porque en el segundo enfoque necesitaría crear y objetar la clase Tuple y luego agregarle valor, lo que creo que es una operación costosa en comparación con devolver el valor en el parámetro out. Sin embargo, si desea devolver varios valores en Tuple Class (que de hecho no se puede lograr simplemente devolviendo un parámetro), iré para un segundo enfoque.


No hay "mejores prácticas". Es con lo que se siente cómodo y lo que funciona mejor en su situación. Siempre que sea coherente con esto, no hay problema con ninguna de las soluciones que ha publicado.


No mencionaste una opción más, que es tener una clase personalizada en lugar de struct. Si los datos tienen una semántica asociada a la cual las funciones pueden operar, o el tamaño de la instancia es lo suficientemente grande (> 16 bytes como regla general), se puede preferir una clase personalizada. El uso de "salir" no se recomienda en la API pública debido a su asociación con los indicadores y que requiere la comprensión de cómo funcionan los tipos de referencia.

https://msdn.microsoft.com/en-us/library/ms182131.aspx

Tuple es bueno para uso interno, pero su uso es incómodo en API pública. Entonces, mi voto es entre struct y class para API pública.