Leí la versión C ++ de esta pregunta pero realmente no la entendí.
¿Alguien puede explicar claramente si se puede hacer y cómo?
Leí la versión C ++ de esta pregunta pero realmente no la entendí.
¿Alguien puede explicar claramente si se puede hacer y cómo?
Respuestas:
En C # 7 y superior, vea esta respuesta .
En versiones anteriores, puede usar la Tupla de .NET 4.0 + :
Por ejemplo:
public Tuple<int, int> GetMultipleValue()
{
return Tuple.Create(1,2);
}
Las tuplas con dos valores tienen Item1
y Item2
como propiedades.
public (int sum, int count) GetMultipleValues() { return (1, 2); }
Este ejemplo fue tomado de nuestro tema de documentación sobre este tema .
Ahora que se ha lanzado C # 7, puede usar la nueva sintaxis Tuples incluida
(string, string, string) LookupName(long id) // tuple return type
{
... // retrieve first, middle and last from data storage
return (first, middle, last); // tuple literal
}
que luego podría usarse así:
var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");
También puede proporcionar nombres a sus elementos (por lo que no son "Elemento1", "Elemento2", etc.). Puede hacerlo agregando un nombre a la firma o los métodos de devolución:
(string first, string middle, string last) LookupName(long id) // tuple elements have names
o
return (first: first, middle: middle, last: last); // named tuple elements in a literal
También se pueden deconstruir, lo cual es una nueva característica bastante agradable:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
Consulte este enlace para ver más ejemplos sobre lo que se puede hacer :)
Puedes usar tres formas diferentes
1. parámetros de ref / out
usando ref:
static void Main(string[] args)
{
int a = 10;
int b = 20;
int add = 0;
int multiply = 0;
Add_Multiply(a, b, ref add, ref multiply);
Console.WriteLine(add);
Console.WriteLine(multiply);
}
private static void Add_Multiply(int a, int b, ref int add, ref int multiply)
{
add = a + b;
multiply = a * b;
}
utilizando:
static void Main(string[] args)
{
int a = 10;
int b = 20;
int add;
int multiply;
Add_Multiply(a, b, out add, out multiply);
Console.WriteLine(add);
Console.WriteLine(multiply);
}
private static void Add_Multiply(int a, int b, out int add, out int multiply)
{
add = a + b;
multiply = a * b;
}
2. struct / class
usando struct:
struct Result
{
public int add;
public int multiply;
}
static void Main(string[] args)
{
int a = 10;
int b = 20;
var result = Add_Multiply(a, b);
Console.WriteLine(result.add);
Console.WriteLine(result.multiply);
}
private static Result Add_Multiply(int a, int b)
{
var result = new Result
{
add = a * b,
multiply = a + b
};
return result;
}
usando clase:
class Result
{
public int add;
public int multiply;
}
static void Main(string[] args)
{
int a = 10;
int b = 20;
var result = Add_Multiply(a, b);
Console.WriteLine(result.add);
Console.WriteLine(result.multiply);
}
private static Result Add_Multiply(int a, int b)
{
var result = new Result
{
add = a * b,
multiply = a + b
};
return result;
}
3. Tupla
Clase de tupla
static void Main(string[] args)
{
int a = 10;
int b = 20;
var result = Add_Multiply(a, b);
Console.WriteLine(result.Item1);
Console.WriteLine(result.Item2);
}
private static Tuple<int, int> Add_Multiply(int a, int b)
{
var tuple = new Tuple<int, int>(a + b, a * b);
return tuple;
}
C # 7 tuplas
static void Main(string[] args)
{
int a = 10;
int b = 20;
(int a_plus_b, int a_mult_b) = Add_Multiply(a, b);
Console.WriteLine(a_plus_b);
Console.WriteLine(a_mult_b);
}
private static (int a_plus_b, int a_mult_b) Add_Multiply(int a, int b)
{
return(a + b, a * b);
}
No puede hacer esto en C #. Lo que puede hacer es tener un out
parámetro o devolver su propia clase (o estructura si desea que sea inmutable).
public int GetDay(DateTime date, out string name)
{
// ...
}
Usando una clase personalizada (o estructura)
public DayOfWeek GetDay(DateTime date)
{
// ...
}
public class DayOfWeek
{
public int Day { get; set; }
public string Name { get; set; }
}
async
métodos. Tuple
es el camino a seguir (Utilizo out
parámetros en las operaciones sincrónicas, aunque, en realidad son útiles en estos casos.)
Si se refiere a devolver múltiples valores, puede devolver una clase / estructura que contiene los valores que desea devolver o usar la palabra clave "out" en sus parámetros, de esta manera:
public void Foo(int input, out int output1, out string output2, out string errors) {
// set out parameters inside function
}
El póster anterior es correcto. No puede devolver múltiples valores de un método C #. Sin embargo, tienes un par de opciones:
Los pros y los contras aquí son a menudo difíciles de resolver. Si devuelve una estructura, asegúrese de que sea pequeña porque las estructuras son de tipo de valor y se pasan a la pila. Si devuelve una instancia de una clase, hay algunos patrones de diseño que tal vez quiera usar para evitar causar problemas: los miembros de las clases se pueden modificar porque C # pasa objetos por referencia (no tiene ByVal como lo hizo en VB )
Finalmente, puede usar parámetros de salida, pero limitaría el uso de esto a escenarios cuando solo tiene un par (como 3 o menos) de parámetros; de lo contrario, las cosas se ponen feas y difíciles de mantener. Además, el uso de parámetros de salida puede ser un inhibidor de la agilidad porque la firma de su método tendrá que cambiar cada vez que necesite agregar algo al valor de retorno, mientras que al devolver una instancia de estructura o clase puede agregar miembros sin modificar la firma del método.
Desde un punto de vista arquitectónico, recomendaría no usar pares clave-valor o diccionarios. Creo que este estilo de codificación requiere "conocimiento secreto" en el código que consume el método. Debe saber de antemano cuáles serán las claves y qué significan los valores, y si el desarrollador que trabaja en la implementación interna cambia la forma en que se crea el diccionario o KVP, podría crear fácilmente una cascada de fallas en toda la aplicación.
Exception
si el segundo valor que desea devolver es disyuntivo del primero: como cuando desea devolver un tipo de valor exitoso o un tipo de valor fallido.
O se devuelve una instancia de clase o utilizar a cabo parámetros. Aquí hay un ejemplo de nuestros parámetros:
void mymethod(out int param1, out int param2)
{
param1 = 10;
param2 = 20;
}
Llámalo así:
int i, j;
mymethod(out i, out j);
// i will be 20 and j will be 10
Hay muchas maneras; pero si no desea crear un nuevo Objeto o estructura o algo así, puede hacer lo siguiente después de C # 7.0 :
(string firstName, string lastName) GetName(string myParameter)
{
var firstName = myParameter;
var lastName = myParameter + " something";
return (firstName, lastName);
}
void DoSomethingWithNames()
{
var (firstName, lastName) = GetName("myname");
}
En C # 7 hay una nueva Tuple
sintaxis:
static (string foo, int bar) GetTuple()
{
return ("hello", 5);
}
Puede devolver esto como un registro:
var result = GetTuple();
var foo = result.foo
// foo == "hello"
También puede usar la nueva sintaxis deconstructor:
(string foo) = GetTuple();
// foo == "hello"
Sin embargo, tenga cuidado con la serialización, todo esto es azúcar sintáctico: en el código compilado real, esto será un Tuple<string, int>
(según la respuesta aceptada ) con Item1
y en Item2
lugar de foo
ybar
. Eso significa que la serialización (o deserialización) utilizará esos nombres de propiedad en su lugar.
Entonces, para la serialización, declare una clase de registro y devuélvala en su lugar.
También nuevo en C # 7 es una sintaxis mejorada para los out
parámetros. Ahora puede declarar la out
línea, que es más adecuada en algunos contextos:
if(int.TryParse("123", out int result)) {
// Do something with result
}
Sin embargo, principalmente usará esto en las propias bibliotecas de .NET, en lugar de en sus propias funciones.
Algunas respuestas sugieren usar parámetros, pero recomiendo no usar esto debido a que no funcionan con métodos asíncronos . Vea esto para más información.
Otras respuestas indicaron el uso de Tuple, que también recomendaría, pero con la nueva característica introducida en C # 7.0.
(string, string, string) LookupName(long id) // tuple return type
{
... // retrieve first, middle and last from data storage
return (first, middle, last); // tuple literal
}
var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");
Se puede encontrar más información aquí .
Hay varias formas de hacerlo. Puedes usar ref
parámetros:
int Foo(ref Bar bar) { }
Esto pasa una referencia a la función permitiendo así que la función modifique el objeto en la pila del código de llamada. Si bien esto no es técnicamente un valor "devuelto", es una forma de hacer que una función haga algo similar. En el código anterior, la función devolvería una int
y (potencialmente) modificación bar
.
Otro enfoque similar es usar un out
parámetro. Un out
parámetro es idéntico a un ref
parámetro con una regla adicional forzada por el compilador. Esta regla es que si pasa un out
parámetro a una función, esa función debe establecer su valor antes de regresar. Además de esa regla, un out
parámetro funciona igual que un ref
parámetro.
El enfoque final (y el mejor en la mayoría de los casos) es crear un tipo que encapsule ambos valores y permita que la función devuelva eso:
class FooBar
{
public int i { get; set; }
public Bar b { get; set; }
}
FooBar Foo(Bar bar) { }
Este enfoque final es más simple y fácil de leer y comprender.
No, no puede devolver múltiples valores de una función en C # (para versiones inferiores a C # 7), al menos no de la forma en que puede hacerlo en Python.
Sin embargo, hay un par de alternativas:
Puede devolver una matriz de objetos tipo con los múltiples valores que desee.
private object[] DoSomething()
{
return new [] { 'value1', 'value2', 3 };
}
Puedes usar out
parámetros.
private string DoSomething(out string outparam1, out int outparam2)
{
outparam1 = 'value2';
outparam2 = 3;
return 'value1';
}
En C # 4, podrá utilizar el soporte integrado para tuplas para manejar esto fácilmente.
Mientras tanto, hay dos opciones.
Primero, puede usar los parámetros ref o out para asignar valores a sus parámetros, que se transfieren a la rutina de llamada.
Esto se ve así:
void myFunction(ref int setMe, out int youMustSetMe);
En segundo lugar, puede resumir sus valores de retorno en una estructura o clase, y devolverlos como miembros de esa estructura. KeyValuePair funciona bien para 2: para más de 2 necesitaría una clase o estructura personalizada.
puedes probar este "KeyValuePair"
private KeyValuePair<int, int> GetNumbers()
{
return new KeyValuePair<int, int>(1, 2);
}
var numbers = GetNumbers();
Console.WriteLine("Output : {0}, {1}",numbers.Key, numbers.Value);
Salida:
Salida: 1, 2
Las clases, estructuras, colecciones y matrices pueden contener múltiples valores. Los parámetros de salida y referencia también se pueden configurar en una función. Es posible devolver valores múltiples en lenguajes dinámicos y funcionales mediante tuplas, pero no en C #.
Principalmente hay dos métodos. 1. Use los parámetros out / ref 2. Devuelva una matriz de objetos
Aquí hay Two
métodos básicos :
1) Uso de ' out
' como parámetro
También puede usar 'out' para las versiones 4.0 y menores.
Ejemplo de 'fuera':
using System;
namespace out_parameter
{
class Program
{
//Accept two input parameter and returns two out value
public static void rect(int len, int width, out int area, out int perimeter)
{
area = len * width;
perimeter = 2 * (len + width);
}
static void Main(string[] args)
{
int area, perimeter;
// passing two parameter and getting two returning value
Program.rect(5, 4, out area, out perimeter);
Console.WriteLine("Area of Rectangle is {0}\t",area);
Console.WriteLine("Perimeter of Rectangle is {0}\t", perimeter);
Console.ReadLine();
}
}
}
Salida:
Área de rectángulo es 20
El perímetro del rectángulo es 18
* Nota: * La out
palabra clave describe parámetros cuyas ubicaciones variables reales se copian en la pila del método llamado, donde esas mismas ubicaciones se pueden reescribir. Esto significa que el método de llamada accederá al parámetro modificado.
2) Tuple<T>
Ejemplo de tupla:
Devolver múltiples valores de DataType usando Tuple<T>
using System;
class Program
{
static void Main()
{
// Create four-item tuple; use var implicit type.
var tuple = new Tuple<string, string[], int, int[]>("perl",
new string[] { "java", "c#" },
1,
new int[] { 2, 3 });
// Pass tuple as argument.
M(tuple);
}
static void M(Tuple<string, string[], int, int[]> tuple)
{
// Evaluate the tuple's items.
Console.WriteLine(tuple.Item1);
foreach (string value in tuple.Item2)
{
Console.WriteLine(value);
}
Console.WriteLine(tuple.Item3);
foreach (int value in tuple.Item4)
{
Console.WriteLine(value);
}
}
}
Salida
perl
java
c#
1
2
3
NOTA: El uso de Tuple es válido desde Framework 4.0 y superior . Tuple
tipo es a class
. Se asignará en una ubicación separada en el montón administrado en la memoria. Una vez que crea el Tuple
, no puede cambiar los valores de su fields
. Esto hace que Tuple
más como a struct
.
Un método que toma un delegado puede proporcionar múltiples valores a la persona que llama. Esto toma prestado de mi respuesta aquí y usa un poco de la respuesta aceptada de Hadas .
delegate void ValuesDelegate(int upVotes, int comments);
void GetMultipleValues(ValuesDelegate callback)
{
callback(1, 2);
}
Las personas que llaman proporcionan una lambda (o una función con nombre) e intellisense ayuda copiando los nombres de las variables del delegado.
GetMultipleValues((upVotes, comments) =>
{
Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments.");
});
Simplemente use de manera OOP una clase como esta:
class div
{
public int remainder;
public int quotient(int dividend, int divisor)
{
remainder = ...;
return ...;
}
}
El miembro de función devuelve el cociente que interesa principalmente a la mayoría de las personas que llaman. Además, almacena el resto como un miembro de datos, al que la persona que llama puede acceder fácilmente después.
De esta manera, puede tener muchos "valores de retorno" adicionales, muy útiles si implementa llamadas a la base de datos o a la red, donde se pueden necesitar muchos mensajes de error, pero solo en caso de que ocurra un error.
Ingresé esta solución también en la pregunta de C ++ a la que se refiere OP.
La versión futura de C # incluirá tuplas con nombre. Eche un vistazo a esta sesión de channel9 para la demostración https://channel9.msdn.com/Events/Build/2016/B889
Pase a las 13:00 para ver las cosas de las tuplas. Esto permitirá cosas como:
(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}
int resultsum = Tally(numbers).sum
(ejemplo incompleto del video)
Podrías usar un objeto dinámico. Creo que tiene mejor legibilidad que Tuple.
static void Main(string[] args){
var obj = GetMultipleValues();
Console.WriteLine(obj.Id);
Console.WriteLine(obj.Name);
}
private static dynamic GetMultipleValues() {
dynamic temp = new System.Dynamic.ExpandoObject();
temp.Id = 123;
temp.Name = "Lorem Ipsum";
return temp;
}
Formas de hacerlo:
1) KeyValuePair (Mejor rendimiento - 0.32 ns):
KeyValuePair<int, int> Location(int p_1, int p_2, int p_3, int p_4)
{
return new KeyValuePair<int,int>(p_2 - p_1, p_4-p_3);
}
2) Tupla - 5.40 ns:
Tuple<int, int> Location(int p_1, int p_2, int p_3, int p_4)
{
return new Tuple<int, int>(p_2 - p_1, p_4-p_3);
}
3) fuera (1.64 ns) o ref 4) Cree su propia clase / estructura personalizada
ns -> nanosegundos
Referencia: valores de retorno múltiple .
puedes probar esto
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
yield return "value1"; yield return "value2";
para no tener que crear explícitamente uno nuevo string[]
?
También puedes usar un OperationResult
public OperationResult DoesSomething(int number1, int number2)
{
// Your Code
var returnValue1 = "return Value 1";
var returnValue2 = "return Value 2";
var operationResult = new OperationResult(returnValue1, returnValue2);
return operationResult;
}
Una respuesta rápida especialmente para el tipo de matriz devuelve:
private int[] SumAndSub(int A, int B)
{
return new[] { A + B, A - B };
}
Utilizando:
var results = SumAndSub(20, 5);
int sum = results[0];
int sub = results[1];