J'ai lu le version C++ de cette question mais je ne l'ai pas vraiment comprise.
Quelqu'un peut-il s'il vous plaît expliquer clairement si cela peut être fait et comment?
Utilisez le tuple de .NET 4.0 + :
Par exemple:
public Tuple<int, int> GetMultipleValue()
{
return Tuple.Create(1,2);
}
Les tuples avec deux valeurs ont Item1
et Item2
en tant que propriétés.
Maintenant que C # 7 est sorti, vous pouvez utiliser la nouvelle syntaxe de Tuples incluse
(string, string, string) LookupName(long id) // Tuple return type
{
... // retrieve first, middle and last from data storage
return (first, middle, last); // Tuple literal
}
qui pourrait alors être utilisé comme ceci:
var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");
Vous pouvez également donner des noms à vos éléments (pour qu’ils ne soient pas "Item1", "Item2", etc.). Vous pouvez le faire en ajoutant un nom à la signature ou aux méthodes de retour:
(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
Ils peuvent aussi être déconstruits, ce qui est une jolie nouvelle fonctionnalité:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
Départ ce lien pour voir plus d'exemples sur ce qui peut être fait :)
Vous pouvez utiliser trois manières différentes
1. Paramètres ref/out
en utilisant 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;
}
en utilisant out
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
en utilisant 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;
}
en utilisant la 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;
}
. Tuple
classe de tuple
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 Tuples
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);
}
Vous ne pouvez pas faire cela en C #. Ce que vous pouvez faire est d’avoir un paramètre out
ou de retourner votre propre classe (ou struct si vous voulez qu’elle soit immuable).
public int GetDay(DateTime date, out string name)
{
// ...
}
public DayOfWeek GetDay(DateTime date)
{
// ...
}
public class DayOfWeek
{
public int Day { get; set; }
public string Name { get; set; }
}
Si vous voulez dire retourner plusieurs valeurs, vous pouvez soit renvoyer une classe/structure contenant les valeurs que vous voulez renvoyer, soit utiliser le mot clé "out" dans vos paramètres, comme suit:
public void Foo(int input, out int output1, out string output2, out string errors) {
// set out parameters inside function
}
L’affiche précédente a raison. Vous ne pouvez pas renvoyer plusieurs valeurs d'une méthode C #. Cependant, vous avez plusieurs options:
Les avantages et les inconvénients sont souvent difficiles à comprendre. Si vous retournez une structure, assurez-vous qu'elle est petite, car les structures sont du type valeur et sont transmises à la pile. Si vous renvoyez une instance d'une classe, vous voudrez peut-être utiliser certains modèles de conception pour éviter de causer des problèmes - les membres de classes peuvent être modifiés car C # transmet les objets par référence (vous n'avez pas ByVal comme vous l'avez fait dans VB ).
Enfin, vous pouvez utiliser des paramètres de sortie, mais je limiterais son utilisation à des scénarios dans lesquels vous ne disposez que de quelques paramètres (comme 3 ou moins) - sinon les choses deviennent laides et difficiles à maintenir. De plus, l'utilisation de paramètres de sortie peut constituer un frein à l'agilité, car la signature de votre méthode devra changer chaque fois que vous devrez ajouter quelque chose à la valeur de retour tout en renvoyant une instance de struct ou de classe, vous pourrez ajouter des membres sans modifier la signature de la méthode.
D'un point de vue architectural, je déconseille d'utiliser des paires clé-valeur ou des dictionnaires. Je trouve que ce style de codage nécessite une "connaissance secrète" dans le code qui consomme la méthode. Il doit savoir à l'avance quelles seront les clés et ce que signifieront les valeurs. Si le développeur travaillant sur l'implémentation interne modifie la manière dont le dictionnaire ou KVP est créé, il pourrait facilement créer une cascade d'échecs dans l'ensemble de l'application.
Vous retournez une instance de classe ou utilisez les paramètres out. Voici un exemple de paramètres out:
void mymethod(out int param1, out int param2)
{
param1 = 10;
param2 = 20;
}
Appelez ça comme ça:
int i, j;
mymethod(out i, out j);
// i will be 20 and j will be 10
Non, vous ne pouvez pas renvoyer plusieurs valeurs d'une fonction en C # (pour les versions inférieures à C # 7), du moins pas comme vous pouvez le faire en Python.
Cependant, il y a quelques alternatives:
Vous pouvez renvoyer un tableau d'objet de type avec les multiples valeurs que vous souhaitez y figurer.
private object[] DoSomething()
{
return new [] { 'value1', 'value2', 3 };
}
Vous pouvez utiliser les paramètres out
.
private string DoSomething(out string outparam1, out int outparam2)
{
outparam1 = 'value2';
outparam2 = 3;
return 'value1';
}
Il y a plusieurs moyens de le faire. Vous pouvez utiliser les paramètres ref
:
int Foo(ref Bar bar) { }
Cela transmet une référence à la fonction, permettant ainsi à la fonction de modifier l'objet dans la pile du code appelant. Bien que ce ne soit pas techniquement une valeur "retournée", c'est une façon de faire en sorte qu'une fonction fasse quelque chose de similaire. Dans le code ci-dessus, la fonction renverrait un int
et (potentiellement) modifier bar
.
Une autre approche similaire consiste à utiliser un paramètre out
. Un paramètre out
est identique à un paramètre ref
avec une règle supplémentaire imposée par le compilateur. Selon cette règle, si vous transmettez un paramètre out
à une fonction, cette fonction doit définir sa valeur avant de renvoyer. Outre cette règle, un paramètre out
fonctionne comme un paramètre ref
.
La dernière approche (et la meilleure dans la plupart des cas) consiste à créer un type qui encapsule les deux valeurs et permet à la fonction de renvoyer ce qui suit:
class FooBar
{
public int i { get; set; }
public Bar b { get; set; }
}
FooBar Foo(Bar bar) { }
Cette dernière approche est plus simple et plus facile à lire et à comprendre.
En C # 4, vous pourrez utiliser la prise en charge intégrée des n-uplets pour gérer cela facilement.
En attendant, il y a deux options.
Tout d'abord, vous pouvez utiliser des paramètres ref ou out pour affecter des valeurs à vos paramètres, qui sont renvoyées à la routine d'appel.
Cela ressemble à:
void myFunction(ref int setMe, out int youMustSetMe);
Deuxièmement, vous pouvez résumer vos valeurs de retour dans une structure ou une classe et les renvoyer en tant que membres de cette structure. KeyValuePair fonctionne bien pour 2 - pour plus de 2, vous aurez besoin d'une classe ou d'une structure personnalisée.
En C # 7, il existe une nouvelle syntaxe Tuple
:
static (string foo, int bar) GetTuple()
{
return ("hello", 5);
}
Vous pouvez renvoyer ceci sous forme d'enregistrement:
var result = GetTuple();
var foo = result.foo
// foo == "hello"
Vous pouvez également utiliser la nouvelle syntaxe de Deconstructor:
(string foo) = GetTuple();
// foo == "hello"
Soyez prudent avec la sérialisation cependant, tout ceci est du sucre syntaxique - dans le code compilé, ce sera un Tupel<string, int>
(comme selon la réponse acceptée ) avec Item1
et Item2
au lieu de foo
et bar
. Cela signifie que la sérialisation (ou la désérialisation) utilisera ces noms de propriété à la place.
Ainsi, pour la sérialisation, déclarez une classe d’enregistrement et retournez-la à la place.
La syntaxe améliorée pour les paramètres out
est également nouvelle dans C # 7. Vous pouvez maintenant déclarer le out
inline, qui convient mieux dans certains contextes:
if(int.TryParse("123", out int result)) {
// Do something with result
}
Cependant, vous l'utiliserez principalement dans les bibliothèques de .NET, plutôt que dans vos propres fonctions.
Certaines réponses suggèrent d’utiliser des paramètres de sortie mais je vous déconseille de l’utiliser car ils ne fonctionnent pas avec les méthodes asynchrones . Voir this pour plus d'informations.
D'autres réponses ont indiqué l'utilisation de Tuple, ce que je recommanderais aussi, mais en utilisant la nouvelle fonctionnalité introduite dans 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}.");
De plus amples informations peuvent être trouvées ici .
vous pouvez essayer ce "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);
Sortie:
Sortie: 1, 2
Les classes, les structures, les collections et les tableaux peuvent contenir plusieurs valeurs. Les paramètres de sortie et de référence peuvent également être définis dans une fonction. Renvoyer plusieurs valeurs est possible dans des langages dynamiques et fonctionnels au moyen de tuples, mais pas en C #.
Voici les méthodes de base Two
:
1) Utilisation de 'out
' en tant que paramètre Vous pouvez également utiliser 'out' pour les versions 4.0 et mineure.
Exemple de 'out':
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();
}
}
}
Sortie:
La superficie du rectangle est de 20
Le périmètre du rectangle est de 18
* Remarque: * Le mot clé out
- décrit les paramètres dont les emplacements de variables réels sont copiés dans la pile de la méthode appelée, où ces mêmes emplacements peut être réécrit. Cela signifie que la méthode appelante aura accès au paramètre modifié.
2) Tuple<T>
Exemple de tuple:
Renvoi de plusieurs valeurs DataType à l'aide de 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);
}
}
}
sortie
Perl
Java
c#
1
2
3
REMARQUE: L'utilisation de Tuple est valable à partir de Framework 4.0 et supérieur .Tuple
le type est un class
. Il sera alloué dans un emplacement distinct sur le segment de mémoire géré en mémoire. Une fois que vous avez créé la Tuple
, vous ne pouvez plus modifier les valeurs de sa fields
. Cela rend la Tuple
plus comme un struct
.
Il existe principalement deux méthodes. 1. Utiliser les paramètres out/ref 2. Renvoyer un tableau d'objets
Une méthode prenant un délégué peut fournir plusieurs valeurs à l'appelant. Ceci emprunte à ma réponse ici et utilise un peu de réponse acceptée de Hadas .
delegate void ValuesDelegate(int upVotes, int comments);
void GetMultipleValues(ValuesDelegate callback)
{
callback(1, 2);
}
Les appelants fournissent un lambda (ou une fonction nommée) et intellisense aide en copiant les noms de variables du délégué.
GetMultipleValues((upVotes, comments) =>
{
Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments.");
});
Il suffit d’utiliser de manière OOP une classe comme celle-ci:
class div
{
public int remainder;
public int quotient(int dividend, int divisor)
{
remainder = ...;
return ...;
}
}
La fonction membre renvoie le quotient qui intéresse principalement la plupart des appelants. De plus, il stocke le reste sous la forme d'un membre de données facilement accessible par l'appelant.
De cette manière, vous pouvez avoir de nombreuses "valeurs de retour" supplémentaires, ce qui est très utile si vous implémentez des appels de base de données ou de réseau, où de nombreux messages d'erreur peuvent être nécessaires, mais uniquement en cas d'erreur.
Je suis entré dans cette solution également dans la question C++ à laquelle OP fait référence.
A partir de this article, vous pouvez utiliser trois options comme indiqué ci-dessus.
KeyValuePair est le moyen le plus rapide.
out est à la seconde.
Le tuple est le plus lent.
Quoi qu'il en soit, cela dépend de ce qui est le mieux pour votre scénario.
La future version de C # va inclure des n-uplets nommés. Regardez cette session channel9 pour la démo https://channel9.msdn.com/Events/Build/2016/B889
Passez à 13h00 pour les trucs des tuples. Cela permettra des choses comme:
(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}
int resultsum = Tally(numbers).sum
(exemple incomplet de la vidéo)
<--Return more statements like this you can -->
public (int,string,etc) Sample( int a, int b)
{
//your code;
return (a,b);
}
Vous pouvez recevoir du code comme
(c,d,etc) = Sample( 1,2);
J'espère que ca fonctionne.
Vous pouvez utiliser un objet dynamique. Je pense que sa lisibilité est meilleure que celle de 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;
}
Façons de le faire:
1) KeyValuePair (meilleure performance - 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) Tuple - 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) or ref 4) Créez votre propre classe/structure personnalisée
ns -> nanosecondes
Référence: multiple-return-values .
tu peux essayer ça
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
Vous pouvez également utiliser 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;
}