Eu li a versão C ++ desta pergunta, mas realmente não a entendi.
Alguém pode explicar claramente se isso pode ser feito e como?
Eu li a versão C ++ desta pergunta, mas realmente não a entendi.
Alguém pode explicar claramente se isso pode ser feito e como?
Respostas:
No C # 7 e acima, veja esta resposta .
Nas versões anteriores, você pode usar a tupla do .NET 4.0 + :
Por exemplo:
public Tuple<int, int> GetMultipleValue()
{
return Tuple.Create(1,2);
}
Tuplas com dois valores têm Item1
e Item2
como propriedades.
public (int sum, int count) GetMultipleValues() { return (1, 2); }
Este exemplo foi retirado do nosso exemplo de tópico de documentação .
Agora que o C # 7 foi lançado, você pode usar a nova sintaxe incluída das Tuplas
(string, string, string) LookupName(long id) // tuple return type
{
... // retrieve first, middle and last from data storage
return (first, middle, last); // tuple literal
}
que poderia ser usado assim:
var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");
Você também pode fornecer nomes para seus elementos (para que eles não sejam "Item1", "Item2" etc.). Você pode fazer isso adicionando um nome à assinatura ou aos métodos de retorno:
(string first, string middle, string last) LookupName(long id) // tuple elements have names
ou
return (first: first, middle: middle, last: last); // named tuple elements in a literal
Eles também podem ser desconstruídos, o que é um novo recurso bastante interessante:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
Confira este link para ver mais exemplos sobre o que pode ser feito :)
Você pode usar três maneiras diferentes
1. parâmetros 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;
}
usando fora:
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. estrutura / classe
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 classe:
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
Classe 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;
}
Tuplas C # 7
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);
}
Você não pode fazer isso em c #. O que você pode fazer é ter umout
parâmetro ou retornar sua própria classe (ou struct, se você quiser que seja imutável).
public int GetDay(DateTime date, out string name)
{
// ...
}
Usando classe personalizada (ou estrutura)
public DayOfWeek GetDay(DateTime date)
{
// ...
}
public class DayOfWeek
{
public int Day { get; set; }
public string Name { get; set; }
}
async
métodos. Tuple
é o caminho a percorrer. (Eu uso out
parâmetros em operações síncronas embora, pois eles são realmente úteis nesses casos.)
Se você quer dizer retornar vários valores, pode retornar uma classe / estrutura contendo os valores que deseja retornar ou usar a palavra-chave "out" em seus parâmetros, da seguinte maneira:
public void Foo(int input, out int output1, out string output2, out string errors) {
// set out parameters inside function
}
O pôster anterior está certo. Você não pode retornar vários valores de um método C #. No entanto, você tem algumas opções:
Os prós e contras aqui são muitas vezes difíceis de descobrir. Se você retornar uma estrutura, verifique se ela é pequena, porque as estruturas são do tipo valor e transmitidas para a pilha. Se você retornar uma instância de uma classe, existem alguns padrões de design aqui que você poderá usar para evitar problemas - os membros das classes podem ser modificados porque o C # passa objetos por referência (você não tem ByVal como no VB )
Finalmente, você pode usar parâmetros de saída, mas eu limitaria o uso disso a cenários em que você tenha apenas alguns (como 3 ou menos) parâmetros - caso contrário, as coisas ficam feias e difíceis de manter. Além disso, o uso de parâmetros de saída pode ser um inibidor da agilidade, pois a assinatura do método precisará ser alterada toda vez que você precisar adicionar algo ao valor de retorno. Ao retornar uma instância de struct ou de classe, você poderá adicionar membros sem modificar a assinatura do método.
Do ponto de vista arquitetural, eu recomendaria não usar pares ou dicionários de valor-chave. Acho que esse estilo de codificação requer "conhecimento secreto" no código que consome o método. Ele deve saber com antecedência o que serão as chaves e o que significam os valores. Se o desenvolvedor que trabalha na implementação interna mudar a maneira como o dicionário ou o KVP é criado, poderá facilmente criar uma cascata de falhas em todo o aplicativo.
Exception
se o segundo valor que você deseja retornar for disjuntivo em relação ao primeiro: como quando você deseja retornar um tipo de valor bem-sucedido ou um tipo de valor malsucedido.
Você quer retornar uma instância de classe ou usar a parâmetros. Aqui está um exemplo de parâmetros externos:
void mymethod(out int param1, out int param2)
{
param1 = 10;
param2 = 20;
}
Chame assim:
int i, j;
mymethod(out i, out j);
// i will be 20 and j will be 10
Há muitas maneiras; mas se você não quiser criar um novo objeto ou estrutura ou algo parecido com isto, faça o seguinte abaixo do 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");
}
No C # 7, há uma nova Tuple
sintaxe:
static (string foo, int bar) GetTuple()
{
return ("hello", 5);
}
Você pode retornar isso como um registro:
var result = GetTuple();
var foo = result.foo
// foo == "hello"
Você também pode usar a nova sintaxe do desconstrutor:
(string foo) = GetTuple();
// foo == "hello"
Tenha cuidado com a serialização, no entanto, tudo isso é açúcar sintático - no código compilado real, este será um Tuple<string, int>
(conforme a resposta aceita ) com Item1
e em Item2
vez de foo
ebar
. Isso significa que a serialização (ou desserialização) usará esses nomes de propriedades.
Portanto, para serialização, declare uma classe de registro e retorne-a.
Também novo no C # 7 é uma sintaxe aprimorada para out
parâmetros. Agora você pode declarar o out
inline, que é mais adequado em alguns contextos:
if(int.TryParse("123", out int result)) {
// Do something with result
}
No entanto, você o utilizará principalmente nas próprias bibliotecas do .NET, e não nas suas próprias funções.
Algumas respostas sugerem o uso de parâmetros, mas eu recomendo não usá-lo porque eles não funcionam com métodos assíncronos . Veja isto para mais informações.
Outras respostas declaradas usando Tuple, que eu recomendaria também, mas usando o novo recurso introduzido no 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}.");
Mais informações podem ser encontradas aqui .
Existem várias maneiras de fazer isso. Você pode usar ref
parâmetros:
int Foo(ref Bar bar) { }
Isso passa uma referência à função, permitindo que a função modifique o objeto na pilha do código de chamada. Embora esse tecnicamente não seja um valor "retornado", é uma maneira de fazer com que uma função faça algo semelhante. No código acima, a função retornaria uma int
e (potencialmente) modificação bar
.
Outra abordagem semelhante é usar um out
parâmetro. Um out
parâmetro é idêntico a um ref
parâmetro com uma regra adicional aplicada pelo compilador. Esta regra é que, se você passar um out
parâmetro para uma função, essa função é necessária para definir seu valor antes de retornar. Além dessa regra, um out
parâmetro funciona exatamente como um ref
parâmetro.
A abordagem final (e a melhor na maioria dos casos) é criar um tipo que encapsule os dois valores e permita que a função retorne:
class FooBar
{
public int i { get; set; }
public Bar b { get; set; }
}
FooBar Foo(Bar bar) { }
Essa abordagem final é mais simples e fácil de ler e entender.
Não, você não pode retornar vários valores de uma função em C # (para versões inferiores a C # 7), pelo menos não da maneira que você pode fazê-lo em Python.
No entanto, existem algumas alternativas:
Você pode retornar uma matriz do tipo de objeto com os vários valores que deseja.
private object[] DoSomething()
{
return new [] { 'value1', 'value2', 3 };
}
Você pode usar out
parâmetros.
private string DoSomething(out string outparam1, out int outparam2)
{
outparam1 = 'value2';
outparam2 = 3;
return 'value1';
}
No C # 4, você poderá usar o suporte interno para tuplas para lidar com isso facilmente.
Enquanto isso, existem duas opções.
Primeiro, você pode usar parâmetros ref ou out para atribuir valores aos seus parâmetros, que são passados de volta à rotina de chamada.
Isso se parece com:
void myFunction(ref int setMe, out int youMustSetMe);
Segundo, você pode agrupar seus valores de retorno em uma estrutura ou classe e passá-los de volta como membros dessa estrutura. KeyValuePair funciona bem para 2 - para mais de 2 você precisaria de uma classe ou estrutura personalizada.
você pode tentar 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);
Resultado :
Saída: 1, 2
Classes, estruturas, coleções e matrizes podem conter vários valores. Os parâmetros de saída e referência também podem ser definidos em uma função. O retorno de vários valores é possível em linguagens dinâmicas e funcionais por meio de tuplas, mas não em C #.
Principalmente dois métodos estão lá. 1. Use out / ref parameters 2. Retorne uma matriz de objetos
Aqui estão os Two
métodos básicos :
1) Uso de ' out
' como parâmetro
Você também pode usar 'out' para as versões 4.0 e secundárias.
Exemplo de 'fora':
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();
}
}
}
Resultado:
Área do retângulo é 20
O perímetro do retângulo é 18
* Nota: * A out
palavra-chave descreve parâmetros cujos locais reais das variáveis são copiados na pilha do método chamado, onde esses mesmos locais podem ser reescritos. Isso significa que o método de chamada acessará o parâmetro alterado.
2) Tuple<T>
Exemplo de tupla:
Retornando vários valores 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);
}
}
}
Resultado
perl
java
c#
1
2
3
NOTA: O uso da Tupla é válido a partir do Framework 4.0 e superior . Tuple
tipo é a class
. Ele será alocado em um local separado na pilha gerenciada na memória. Depois de criar o Tuple
, você não poderá alterar os valores dele fields
. Isso faz com que Tuple
mais pareça um struct
.
Um método que leva um delegado pode fornecer vários valores ao chamador. Isso toma emprestado minha resposta aqui e usa um pouco da resposta aceita por Hadas .
delegate void ValuesDelegate(int upVotes, int comments);
void GetMultipleValues(ValuesDelegate callback)
{
callback(1, 2);
}
Os chamadores fornecem uma lambda (ou uma função nomeada) e o intellisense ajuda copiando os nomes das variáveis do delegado.
GetMultipleValues((upVotes, comments) =>
{
Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments.");
});
Basta usar de maneira OOP uma classe como esta:
class div
{
public int remainder;
public int quotient(int dividend, int divisor)
{
remainder = ...;
return ...;
}
}
O membro da função retorna o quociente no qual a maioria dos chamadores está interessada. Além disso, armazena o restante como um membro de dados, que é facilmente acessível pelo chamador posteriormente.
Dessa forma, você pode ter muitos "valores de retorno" adicionais, muito úteis se você implementar chamadas de banco de dados ou de rede, onde muitas mensagens de erro podem ser necessárias, mas apenas no caso de ocorrer um erro.
Eu entrei nessa solução também na pergunta C ++ à qual o OP está se referindo.
A versão futura do C # incluirá tuplas nomeadas. Dê uma olhada nesta sessão do canal9 para a demonstração https://channel9.msdn.com/Events/Build/2016/B889
Pule para 13:00 para o material da tupla. Isso permitirá coisas como:
(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}
int resultsum = Tally(numbers).sum
(exemplo incompleto do vídeo)
Você poderia usar um objeto dinâmico. Eu acho que tem melhor legibilidade 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;
}
Maneiras de fazer isso:
1) KeyValuePair (melhor desempenho - 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) out (1,64 ns) ou ref 4) Crie sua própria classe / estrutura personalizada
ns -> nanossegundos
Referência: multiple-return-values .
você pode tentar isso
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
yield return "value1"; yield return "value2";
para não precisar criar explicitamente um novo string[]
?
Você também pode usar um 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;
}
Uma resposta rápida, especialmente para retornos de tipo de matriz:
private int[] SumAndSub(int A, int B)
{
return new[] { A + B, A - B };
}
Usando:
var results = SumAndSub(20, 5);
int sum = results[0];
int sub = results[1];