Meerdere waarden retourneren naar een methodeaanroeper

Ik heb de C++-versie van deze vraaggelezen, maar niet echt begrijp het.

Kan iemand alsjeblieft duidelijk uitleggen of het kan en hoe?


Antwoord 1, autoriteit 100%

Zie in C# 7 en hoger dit antwoord.

In eerdere versies kunt u de Tuple van .NET 4.0+ gebruiken :

Bijvoorbeeld:

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

Tuples met twee waarden hebben Item1en Item2als eigenschappen.


Antwoord 2, autoriteit 85%

Nu C# 7 is uitgebracht, kunt u de nieuwe meegeleverde Tuples-syntaxis gebruiken

(string, string, string) LookupName(long id) // tuple return type
{
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal
}

die dan als volgt kan worden gebruikt:

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

Je kunt ook namen geven aan je elementen (dus niet “Item1”, “Item2” etc.). U kunt dit doen door een naam toe te voegen aan de handtekening of de retourmethoden:

(string first, string middle, string last) LookupName(long id) // tuple elements have names

of

return (first: first, middle: middle, last: last); // named tuple elements in a literal

Ze kunnen ook worden gedeconstrueerd, wat een mooie nieuwe functie is:

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

Bekijk dit linkom meer voorbeelden te zien van wat gedaan kan worden 🙂


Antwoord 3, autoriteit 35%

U kunt drie verschillende manieren gebruiken

1. ref / out-parameters

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

uitgebruiken:

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

struct gebruiken:

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

met behulp van klasse:

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

tuple klas

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

4, Autoriteit 11%

Je kunt dit niet doen in C#. Wat je kunt doen is een outparameter hebben of je eigen klasse retourneren (of struct als je wilt dat deze onveranderlijk is).

Out-parameter gebruiken:

public int GetDay(DateTime date, out string name)
{
  // ...
}

Aangepaste klasse (of struct) gebruiken

public DayOfWeek GetDay(DateTime date)
{
  // ...
}
public class DayOfWeek
{
  public int Day { get; set; }
  public string Name { get; set; }
}

Antwoord 5, autoriteit 6%

Als u meerdere waarden wilt retourneren, kunt u ofwel een klasse/structeur retourneren die de waarden bevat die u wilt retourneren, of u kunt het trefwoord “out” gebruiken voor uw parameters, zoals:

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

Antwoord 6, autoriteit 5%

De vorige poster heeft gelijk. U kunt niet meerdere waarden van een C#-methode retourneren. U heeft echter een aantal opties:

  • Retourneer een structuur die meerdere leden bevat
  • Retourneer een instantie van een klasse
  • Gebruik uitvoerparameters (met behulp van de trefwoorden outof ref)
  • Gebruik een woordenboek of sleutel/waarde-paar als uitvoer

De voor- en nadelen hier zijn vaak moeilijk te achterhalen. Als u een structuur retourneert, zorg er dan voor dat deze klein is, want structs zijn van het waardetype en worden doorgegeven aan de stapel. Als u een instantie van een klasse retourneert, zijn er hier enkele ontwerppatronen die u mogelijk wilt gebruiken om problemen te voorkomen – leden van klassen kunnen worden gewijzigd omdat C # objecten door verwijzing doorgeeft (u hebt geen ByVal zoals u deed in VB ).

Ten slotte kun je uitvoerparameters gebruiken, maar ik zou het gebruik hiervan beperken tot scenario’s waarin je maar een paar (zoals 3 of minder) parameters hebt – anders wordt het lelijk en moeilijk te onderhouden. Het gebruik van uitvoerparameters kan ook een rem zijn op behendigheid, omdat uw methodehandtekening elke keer moet worden gewijzigd als u iets aan de retourwaarde moet toevoegen, terwijl u bij het retourneren van een struct of klasse-instantie leden kunt toevoegen zonder de methodehandtekening te wijzigen.

Vanuit architectonisch oogpunt zou ik het gebruik van sleutel-waardeparen of woordenboeken afraden. Ik vind dat deze stijl van coderen “geheime kennis” vereist in code die de methode verbruikt. Het moet van tevoren weten wat de sleutels zullen zijn en wat de waarden betekenen en als de ontwikkelaar die aan de interne implementatie werkt, de manier verandert waarop het woordenboek of KVP wordt gemaakt, kan dit gemakkelijk een storingscascade in de hele applicatie veroorzaken.


Antwoord 7, autoriteit 4%

In C#7 is er een nieuwe Tuple-syntaxis:

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

U kunt dit retourneren als een record:

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

U kunt ook de nieuwe syntaxis van de deconstructor gebruiken:

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

Wees voorzichtig met serialisatie, dit alles is echter syntactische suiker – in de werkelijke gecompileerde code is dit een Tuple<string, int>(als Per het geaccepteerde antwoord ) met Item1en Item2in plaats van fooen bar. Dat betekent dat serialisatie (of deseriorization) in plaats daarvan die eigendomsnamen zal gebruiken.

Dus, voor serialisatie, verklaar een recordklasse en retourneer dat in plaats daarvan.

Ook nieuw in C # 7 is een verbeterde syntaxis voor outparameters. U kunt nu de outInline declareren, die beter geschikt is in sommige contexten:

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

Meestal gebruik je dit echter in .NET’s eigen bibliotheken, in plaats van in je eigen functies.


8, Autoriteit 4%

Er is vele manier; Maar als je geen nieuw object of structuur of zoiets wilt maken, kun je hieronder doen na 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");
    }

9, Autoriteit 3%

U retourneert u een Class-instantie of gebruik uit parameters. Hier is een voorbeeld van OUT-parameters:

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

Noem het zo:

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

Antwoord 10, autoriteit 2%

Sommige antwoorden suggereren het gebruik van out parameters, maar ik raad aan
gebruiken dit niet vanwege ze werken niet met asynchrone methoden. Zien
ditvoor meer informatie.

Andere antwoorden werden gegeven met behulp van Tuple, wat ik ook zou aanraden, maar met de nieuwe functie die in C# 7.0 is geïntroduceerd.

(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}.");

Meer informatie is te vinden hier.


Antwoord 11, autoriteit 2%

Er zijn verschillende manieren om dit te doen. U kunt refparameters gebruiken:

int Foo(ref Bar bar) { }

Dit geeft een verwijzing naar de functie door, waardoor de functie het object in de stack van de aanroepende code kan wijzigen. Hoewel dit technisch gezien geen “geretourneerde” waarde is, is het een manier om een functie iets soortgelijks te laten doen. In de bovenstaande code zou de functie een intretourneren en (mogelijk) barwijzigen.

Een andere vergelijkbare benadering is het gebruik van een outparameter. Een outparameter is identiek aan een refparameter met een extra, door de compiler afgedwongen regel. Deze regel is dat als u een parameter outdoorgeeft aan een functie, die functie zijn waarde moet instellen voordat hij terugkeert. Naast die regel werkt een outparameter net als een refparameter.

De laatste benadering (en in de meeste gevallen de beste) is om een type te maken dat beide waarden inkapselt en de functie toe te staan dat terug te geven:

class FooBar 
{
    public int i { get; set; }
    public Bar b { get; set; }
}
FooBar Foo(Bar bar) { }

Deze definitieve benadering is eenvoudiger en gemakkelijker te lezen en te begrijpen.


Antwoord 12, autoriteit 2%

Nee, je kunt niet meerdere waarden van een functie in C# retourneren (voor versies lager dan C# 7), althans niet op de manier waarop je dat in Python kunt doen.

Er zijn echter een paar alternatieven:

Je kunt een array van type object retourneren met de meerdere waarden die je erin wilt hebben.

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

U kunt outparameters gebruiken.

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

Antwoord 13

In C# 4 kun je ingebouwde ondersteuning voor tuples gebruiken om dit gemakkelijk af te handelen.

In de tussentijd zijn er twee opties.

Ten eerste kun je ref of out-parameters gebruiken om waarden aan je parameters toe te wijzen, die worden doorgegeven aan de aanroeproutine.

Dit ziet er als volgt uit:

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

Ten tweede kunt u uw retourwaarden samenvatten in een structuur of klasse en ze teruggeven als leden van die structuur. KeyValuePair werkt goed voor 2 personen – voor meer dan 2 heeft u een aangepaste klasse of struct nodig.


Antwoord 14

<--Return more statements like this you can --> 
public (int,string,etc) Sample( int a, int b)  
{
    //your code;
    return (a,b);  
}

Je kunt een code ontvangen zoals

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

Ik hoop dat het werkt.


Antwoord 15

u kunt dit “KeyValuePair” proberen

private KeyValuePair<int, int> GetNumbers()
{
  return new KeyValuePair<int, int>(1, 2);
}
var numbers = GetNumbers();
Console.WriteLine("Output : {0}, {1}",numbers.Key, numbers.Value);

Uitvoer:

Uitvoer: 1, 2


Antwoord 16

Klassen, structuren, verzamelingen en arrays kunnen meerdere waarden bevatten. Uitgangs- en referentieparameters kunnen ook in een functie worden ingesteld. Meerdere waarden retourneren is mogelijk in dynamische en functionele talen door middel van tuples, maar niet in C#.


Antwoord 17

Er zijn hoofdzakelijk twee methoden.
1. Gebruik out/ref-parameters
2. Retourneer een reeks objecten


18

Een methode die een afgevaardigde neemt, kan meerdere waarden leveren aan de beller. Deze leent uit mijn antwoord hier en gebruikt een beetje van Hada’s geaccepteerd antwoord .

delegate void ValuesDelegate(int upVotes, int comments);
void GetMultipleValues(ValuesDelegate callback)
{
    callback(1, 2);
}

bellers bieden een lambda (of een benoemde functie) en IntelliSense helpt bij het kopiëren van de variabele namen van de afgevaardigde.

GetMultipleValues((upVotes, comments) =>
{
     Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments.");
});

19

van Dit artikel, kunt u drie opties gebruiken als hierboven genoemde posten.

KeyValuePairis de snelste manier.

uitis op de tweede plaats.

Tupleis de langzaamste.

Hoe dan ook, dit hangt af van wat het beste is voor uw scenario.


Antwoord 20

Gebruik gewoon op OOP-manier een klasse als deze:

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

Het functielid retourneert het quotiënt waarin de meeste bellers voornamelijk geïnteresseerd zijn. Bovendien slaat het de rest op als een datalid, dat daarna gemakkelijk toegankelijk is voor de beller.

Op deze manier kunt u veel extra “retourwaarden” hebben, erg handig als u database- of netwerkaanroepen implementeert, waar veel foutmeldingen nodig kunnen zijn, maar alleen als er een fout optreedt.

Ik heb deze oplossing ook ingevoerd in de C++-vraag waar OP naar verwijst.


Antwoord 21

Toekomstige versie van C# zal benoemde tuples bevatten.
Bekijk deze channel9 sessie voor de demo
https://channel9.msdn.com/Events/Build/2016/B889

Ga naar 13.00 uur voor de tuple-dingen. Dit maakt dingen mogelijk zoals:

(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}
int resultsum = Tally(numbers).sum

(onvolledig voorbeeld uit video)


Antwoord 22

Je zou een dynamisch object kunnen gebruiken. Ik denk dat het beter leesbaar is dan 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;
}

Antwoord 23

Manieren om het te doen:

1) KeyValuePair (Beste prestatie – 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) uit (1,64 ns) of ref
4) Maak je eigen aangepaste klasse/structeur

ns -> nanoseconden

Referentie: multiple-return-values.


Antwoord 24

U kunt ook een OperationResult gebruiken

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

Antwoord 25

u kunt dit proberen

public IEnumerable<string> Get()
 {
     return new string[] { "value1", "value2" };
 }

Other episodes