Question

Je lis la version C ++ de cette question mais n'a pas vraiment comprendre.

Quelqu'un peut-il expliquer clairement si s'il vous plaît, il peut être fait et comment?

Était-ce utile?

La solution

Utilisez .NET 4.0 + 's Tuple :

Par exemple:

public Tuple<int, int> GetMultipleValue()
{
     return Tuple.Create(1,2);
}

tuples à deux valeurs ont Item1 et Item2 en tant que propriétés.

Autres conseils

Maintenant que C # 7 a été libéré, vous pouvez utiliser la nouvelle syntaxe Tuples inclus

(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 ensuite être utilisé comme ceci:

var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");

Vous pouvez également fournir des noms à vos éléments (donc ils ne sont pas « Item1 », « Item2 », etc.). Vous pouvez le faire en ajoutant un nom à la signature ou les 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 également être déconstruit, qui est une nouvelle fonctionnalité assez agréable:

(string first, string middle, string last) = LookupName(id1); // deconstructing declaration

Consultez ce lien pour voir plus d'exemples sur ce qui peut être fait:)

Vous pouvez utiliser trois façons 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 sur:

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 / classe

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;
}

3. Tuple

classe 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 le faire en C #. Ce que vous pouvez faire est d'avoir un paramètre out ou retourner votre propre classe (ou struct si vous voulez qu'il soit immuable).

En utilisant des paramètres
public int GetDay(DateTime date, out string name)
{
  // ...
}
En utilisant la classe personnalisée (ou struct)
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 retourner une classe / struct contenant les valeurs que vous souhaitez revenir, ou utiliser le mot-clé « out » sur vos paramètres, comme suit:

public void Foo(int input, out int output1, out string output2, out string errors) {
    // set out parameters inside function
}

affiche précédente est juste. Vous ne pouvez pas renvoyer plusieurs valeurs à partir d'une méthode C #. Cependant, vous avez deux options:

  • Retour d'une structure qui contient plusieurs membres
  • Retour d'une instance d'une classe
  • Utilisez les paramètres de sortie (en utilisant le sur ou ref mots-clés)
  • Utiliser une paire de dictionnaire ou clé-valeur en tant que sortie

Les avantages et les inconvénients ici sont souvent difficiles à comprendre. Si vous retournez une structure, assurez-vous qu'il est petit parce struct sont le type de valeur et transmis sur la pile. Si vous retournez une instance d'une classe, il y a quelques modèles de conception ici que vous pouvez utiliser pour éviter les problèmes causant - les membres des classes peuvent être modifiés parce que C # passe des objets par référence (vous n'avez pas ByVal comme vous l'avez fait en VB ).

Enfin, vous pouvez utiliser les paramètres de sortie, mais je voudrais limiter l'utilisation de ce à des scénarios lorsque vous avez seulement un couple (comme 3 ou moins) des paramètres - sinon les choses deviennent laides et difficiles à maintenir. En outre, l'utilisation de paramètres de sortie peut être un inhibiteur de l'agilité parce que votre signature de la méthode devra changer chaque fois que vous avez besoin d'ajouter quelque chose à la valeur de retour alors que le retour d'une instance de struct ou classe, vous pouvez ajouter des membres sans modifier la signature de la méthode.

Du point de vue architectural que je recommande contre l'utilisation de paires clé-valeur ou des dictionnaires. Je trouve ce style de codage exige « connaissance secrète » dans le code qui consomme la méthode. Il doit savoir à l'avance ce que les clés vont être et ce que les valeurs moyennes et si le développeur qui travaille sur la mise en œuvre interne modifie la façon dont le dictionnaire ou KVP est créé, il pourrait facilement créer une cascade d'échec dans toute l'application.

Vous réintégrez instance de classe ou utilisez sur paramètres. Voici un exemple de paramètres out:

void mymethod(out int param1, out int param2)
{
    param1 = 10;
    param2 = 20;
}

Appel comme ceci:

int i, j;
mymethod(out i, out j);
// i will be 20 and j will be 10

Il y a plusieurs façons de le faire. Vous pouvez utiliser les paramètres de ref:

int Foo(ref Bar bar) { }

passe une référence à la fonction qui permet à la fonction de modifier l'objet dans la pile du code d'appel. Bien que ce ne soit pas techniquement une valeur « retour » est un moyen d'avoir une fonction de faire quelque chose similaire. Dans le code ci-dessus la fonction reviendrait un int et (potentiellement) modifier bar.

Une autre approche similaire consiste à utiliser un paramètre out. Un paramètre de out est identique à un paramètre de ref avec une règle supplémentaire, exécutée compilateur. Cette règle est que si vous passez un paramètre out en fonction, cette fonction est nécessaire pour définir sa valeur avant de retourner. En plus de cette règle, un paramètre de out fonctionne comme un paramètre ref.

L'approche finale (et le meilleur dans la plupart des cas) est de créer un type qui encapsule les deux valeurs et permettent la fonction de revenir que:

class FooBar 
{
    public int i { get; set; }
    public Bar b { get; set; }
}

FooBar Foo(Bar bar) { }

Cette approche finale est plus simple et plus facile à lire et à comprendre.

Non, vous ne pouvez pas revenir plusieurs valeurs d'une fonction en C # (pour les versions inférieures à C # 7), au moins pas de la manière que vous pouvez le faire en Python.

Cependant, il y a quelques alternatives:

Vous pouvez retourner un tableau d'objet de type avec les multiples valeurs que vous voulez en elle.

private object[] DoSomething()
{
    return new [] { 'value1', 'value2', 3 };
}

Vous pouvez utiliser les paramètres de out.

private string DoSomething(out string outparam1, out int outparam2)
{
    outparam1 = 'value2';
    outparam2 = 3;
    return 'value1';
}

En C # 4, vous serez en mesure d'utiliser le support intégré pour tuples pour gérer facilement.

En attendant, il y a deux options.

D'abord, vous pouvez utiliser ref ou des paramètres pour attribuer des valeurs à vos paramètres, qui sont transmis à la routine de retour d'appel.

Cela ressemble à:

void myFunction(ref int setMe, out int youMustSetMe);

Deuxièmement, vous pouvez envelopper vos valeurs de retour dans une structure ou une classe, et de les transmettre de retour en tant que membres de cette structure. KeyValuePair fonctionne bien pour 2 -. Pour plus de 2 vous auriez besoin d'une classe personnalisée ou struct

En C # 7 Il y a une nouvelle syntaxe Tuple:

static (string foo, int bar) GetTuple()
{
    return ("hello", 5);
}

Vous pouvez retourner cela comme un enregistrement:

var result = GetTuple();
var foo = result.foo
// foo == "hello"

Vous pouvez également utiliser la nouvelle syntaxe deconstructor:

(string foo) = GetTuple();
// foo == "hello"

Soyez prudent avec sérialisation cependant, tout cela est du sucre syntaxique - dans le code compilé réel ce sera un Tupel<string, int> (comme par l'accepté réponse ) avec Item1 et Item2 au lieu de foo et bar. Cela signifie que la sérialisation (ou désérialisation) utiliseront ces noms de propriété à la place.

Alors, pour la sérialisation déclarer une classe d'enregistrement et de retour qu'au lieu.

Une autre nouveauté en C # 7 est une syntaxe améliorée pour les paramètres de out. Vous pouvez maintenant déclarer la ligne de out, ce qui est mieux adapté dans certains contextes:

if(int.TryParse("123", out int result)) {
    // Do something with result
}

Cependant, la plupart du temps vous utiliserez ce dans ses propres bibliothèques de .NET, plutôt que dans votre propre fonctions.

  

Quelques réponses suggèrent d'utiliser sur les paramètres mais je recommande   ne pas utiliser ce dû à ils ne fonctionnent pas avec les méthodes async . Voir    cette pour plus d'informations.

D'autres réponses ont déclaré à l'aide Tuple, que je recommande aussi, mais en utilisant la nouvelle fonctionnalité introduite 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}.");

Pour plus d'informations peuvent être trouvées ici .

vous pouvez essayer cette "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

Classes, structures, collections et tableaux peuvent contenir plusieurs valeurs. Les paramètres de sortie et de référence peuvent également être réglés en fonction. Retour plusieurs valeurs est possible dans les langages dynamiques et fonctionnels au moyen de tuples, mais pas en C #.

Principalement deux méthodes sont là. 1. Utilisez les paramètres ref / out 2. Retourne un tableau d'objets

Voici les méthodes de Two de base:

1) Utilisation de 'out' en tant que paramètre Vous pouvez utiliser « out » pour les 4.0 et les versions mineures aussi.

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:

aire du rectangle est 20

Périmètre du rectangle est 18

* Note: * Le out-mot-clé décrit les paramètres dont les emplacements variables réelles sont copiées sur la pile de la méthode appelée, où ces mêmes endroits peuvent être réécrites. Cela signifie que la méthode appelante accéder au paramètre modifié.

2) Tuple<T>

Exemple de nuplet:

De retour des valeurs DataType multiples à l'aide 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

NOTE: L'utilisation de Tuple est valable du Framework 4.0 et au-dessus type .Tuple est un class. Il sera affecté dans un autre endroit sur le tas géré en mémoire. Une fois que vous créez le Tuple, vous ne pouvez pas modifier les valeurs de son fields. Cela rend le Tuple plus comme un struct.

Une méthode prenant un délégué peut fournir des valeurs multiples à l'appelant. Cela emprunte à ma réponse et utilise un peu de 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 POO une classe comme ceci:

class div
{
    public int remainder;

    public int quotient(int dividend, int divisor)
    {
        remainder = ...;
        return ...;
    }
}

Le membre de la fonction retourne le quotient que la plupart des appelants sont principalement intéressés par. En outre, il stocke le reste en tant que membre de données, qui est facilement accessible par l'appelant par la suite.

De cette façon, vous pouvez avoir beaucoup de « valeurs de retour » supplémentaires, très utile si vous implémentez base de données ou des appels en réseau, où beaucoup de messages d'erreur peuvent être nécessaires, mais uniquement en cas d'erreur.

Je suis entré dans cette solution aussi dans le C ++ question OP fait référence.

De cet article , vous pouvez utiliser trois options postes ci-dessus dit.

KeyValuePair est moyen le plus rapide.

sur est à la seconde.

Tuple est le plus lent.

En tout cas, cela est dépend de ce qui est le meilleur pour votre scénario.

future version de C # va inclure tuples nommé. Jetez un oeil à cette session de Channel9 pour la démo https://channel9.msdn.com/Events/Build/2016/B889

Aller à 13h00 pour les choses de tuple. 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)

Vous pouvez utiliser un objet dynamique. Je pense qu'il a une meilleure lisibilité 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;
}
<--Return more statements like this you can --> 

public (int,string,etc) Sample( int a, int b)  
{
    //your code;
    return (a,b);  
}

Vous pouvez recevoir le code comme

(c,d,etc) = Sample( 1,2);

J'espère que cela fonctionne.

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) à (1,64 ns) ou ref 4) Créer votre propre classe / struct personnalisé

ns -> nanosecondes

Référence: multiples retour valeurs

.

vous pouvez essayer

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;
}

Il y a beaucoup de manière; mais si vous ne voulez pas créer un nouvel objet ou une structure ou quelque chose comme cela, vous pouvez faire comme ci-dessous après 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");

    }

Aujourd'hui, les programmeurs ont besoin de temps et méthodes unforgotable. Une solution simple, rapide et travail:

private int[] SumAndSub(int A, int B)
{
    return new[] { A + B , A - B };
}

Utilisation dans quelque part;

var results = SumAndSub(20, 5);
int sum = results[0];
int sub = results[0];
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top