Kaip galiu grąžinti kelias reikšmes iš funkcijos C #?

Aš perskaičiau šio klausimo C + + versiją, bet tikrai nesupratau.

Ar kas nors gali paaiškinti, ar tai aišku ir kaip?

327
14 апр. Pelenai nustatomi 14 d. 2009-04-14 18:11 '09, 18:11 PM 2009-04-14 18:11
@ 26 atsakymai

Naudokite .NET 4. 0+ Tuple :

Pavyzdžiui:

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

Dviejų reikšmių Item1 turi Item1 ir 2 Item2 kaip savybes.

517
23 апр. Atsakymą Hadas pateikė balandžio 23 d 2012-04-23 13:24 '12, 13:24, 2012-04-23 13:24

Dabar, kai „C # 7“ yra paleistas, galite naudoti naują įtrauktą sintaksę „Tuples“

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

kuris gali būti naudojamas taip:

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

Taip pat galite nurodyti savo daiktų pavadinimus (taip, kad jie nebūtų „elementas1“, „elementas2“ ir tt). Tai galite padaryti pridėdami parašo arba grąžinimo metodų pavadinimą:

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

arba

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

Jie taip pat gali būti dekonstruoti, o tai yra gana gražus naujas bruožas:

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

Peržiūrėkite šią nuorodą ir pamatysite daugiau pavyzdžių, ką galima padaryti :)

229
05 апр. Francisco Noriega atsakymas 05 Bal 2016-04-05 23:19 '16 at 23:19 PM 2016-04-05 23:19

Galite naudoti tris skirtingus metodus.

1. ref / out parametrai

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

naudojant:

 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. struktūra / klasė

naudojant struktūrą:

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

naudojant klasę:

 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

Klasės paketas

 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 eilutės

 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); } 
129
04 июня '15 в 2:04 2015-06-04 02:04 Atsakymą davė Devrim Altınkurt birželio 4 d. 15 d. 2:04 2015-06-04 02:04

Negalite to padaryti C #. Tai, ką galite padaryti, turi out parametrą arba grąžinti savo klasę (ar struktūrą, jei norite, kad ji būtų pastovi).

Naudokite parametrą
 public int GetDay(DateTime date, out string name) { // ... } 
Pasirinktinės klasės (ar struktūros) naudojimas
 public DayOfWeek GetDay(DateTime date) { // ... } public class DayOfWeek { public int Day { get; set; } public string Name { get; set; } } 
75
14 апр. Samuelio atsakymas, pateiktas balandžio 14 d 2009-04-14 18:16 '09, 18:16 PM 2009-04-14 18:16

Jei norite grąžinti kelias reikšmes, galite grąžinti klasę / struktūrą, kurioje yra vertybės, kurias norite grąžinti, arba naudokite „iš“ raktinį žodį savo parametrams, pavyzdžiui:

 public void Foo(int input, out int output1, out string output2, out string errors) { // set out parameters inside function } 
37
14 апр. Chris Doggett atsakymas, pateiktas balandžio 14 d 2009-04-14 18:15 '09, 18:15 PM 2009-04-14 18:15

Ankstesnis plakatas yra teisus. Negalite grąžinti keleto reikšmių iš C # metodo. Tačiau turite kelias parinktis:

  • Grąžina struktūrą, kurioje yra keli elementai.
  • Grąžina klasės egzempliorių
  • Naudokite išvesties parametrus (naudodami išeinančius arba ref.
  • Naudokite žodyną arba raktų vertės porą kaip išvestį.

Čia dažnai sunku suprasti privalumus ir trūkumus. Jei grąžinate struktūrą, įsitikinkite, kad ji yra maža, nes struktūra yra vertės rūšis ir yra perduodama į kaminą. Jei grąžinate klasės egzempliorių, yra keletas dizaino modelių, kuriuos galite naudoti, kad išvengtumėte problemų - klasės nariai gali būti keičiami, nes C # perduoda objektus pagal nuorodą (jūs neturite „ByVal“, kaip jūs darėte VB).

Galiausiai, jūs galite naudoti išvesties parametrus, bet aš apriboju naudojimąsi scenarijais, kai turite keletą (pvz., 3 ar mažiau) parametrų - priešingu atveju viskas tampa negraži ir sunkiai prižiūrima. Be to, naudojant išvesties parametrus gali būti lankstumo inhibitorius, nes jūsų metodo parašas turi keisti kiekvieną kartą, kai reikia pridėti kažką grąžinimo vertei, o grąžinus struktūros ar klasės egzempliorių, galite pridėti elementų nekeičiant metodo parašo.

Architektūriniu požiūriu norėčiau rekomenduoti nenaudoti pagrindinių verčių porų ar žodynų. Manau, kad šis kodavimo stilius reikalauja „slaptų žinių“ kode, kuriame naudojamas šis metodas. Jis turi iš anksto žinoti, kas bus raktai ir ką reiškia reikšmė, ir jei kūrėjas, dirbantis vidiniame diegime, keičia žodyno ar KVP kūrimo būdą, jis gali lengvai sukurti nesėkmių kaskadą.

33
14 апр. Kevino Hoffmano atsakymas, pateiktas balandžio 14 d 2009-04-14 18:18 '09, 18:18, 2009-04-14 18:18

Grąžinate klasės ar naudojimo parametrų egzempliorių. Pateikiamas išvesties parametrų pavyzdys:

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

Skambinkite taip:

 int i, j; mymethod(out i, out j); // i will be 20 and j will be 10 
18
14 апр. Atsakymas pateikiamas Keltex 14 d. 2009-04-14 18:16 '09, 18:16 PM 2009-04-14 18:16

Yra keletas būdų tai padaryti. Galite naudoti ref parametrus:

 int Foo(ref Bar bar) { } 

Tai perduoda nuorodą į funkciją, tokiu būdu leidžiant funkcijai keisti skambinančiojo kodo kamino objektą. Nors tai techniškai nėra „grįžimo“ vertė, tai yra būdas tai daryti. Pirmiau pateiktame kode funkcija grąžina int ir (galbūt) bar .

Kitas panašus metodas yra išnaudoti parametrą. out parametras yra identiškas ref parametrams su papildoma kompiliatoriaus taisykle. Ši taisyklė yra ta, kad jei funkcijai perduodate parametrą, ši funkcija turi nustatyti jo vertę prieš grąžindama. Be šios taisyklės, out parametras veikia taip pat kaip ir ref parametras.

Galutinis požiūris (ir geriausias daugeliu atvejų) yra sukurti tipą, kuris apimtų abi vertybes ir leidžia funkcijai grąžinti:

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

Šis galutinis požiūris yra lengviau ir lengviau skaitomas ir suprantamas.

11
14 апр. Atsakyti Andrew Hare 14 d. 2009-04-14 18:19 '09, 18:19, 2009-04-14 18:19

Ne, negalite grąžinti keleto reikšmių iš C # funkcijos (versijoms, esančioms žemiau C # 7), bent jau ne taip, kaip galite tai padaryti „Python“.

Tačiau yra keletas alternatyvų:

Galite grąžinti tipo objektų masyvą su keliomis norimomis reikšmėmis.

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

Galite naudoti parametrus.

 private string DoSomething(out string outparam1, out int outparam2) { outparam1 = 'value2'; outparam2 = 3; return 'value1'; } 
10
14 апр. atsakymas duotas dustyburwell 14 balandis 2009-04-14 18:18 '09, 18:18, 2009-04-14 18:18

„C # 4“ galite naudoti vietinę palaikymą, skirtą „tuples“, kad tai būtų lengva.

Tuo pačiu metu yra dvi galimybės.

Pirma, galite naudoti ref arba out parametrus, kad priskirtumėte parametrus, kurie bus grąžinti į skambinimo procedūrą.

Tai atrodo taip:

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

Antra, galite sugrąžinti grąžinimo vertes į struktūrą ar klasę ir perduoti jas kaip šios struktūros narius. KeyValuePair puikiai tinka 2 - daugiau nei 2 jums reikia pasirinktos klasės ar struktūros.

10
14 апр. atsakymą pateikė Reed Copsey balandžio 14 d 2009-04-14 18:17 '09, 18:17 PM 2009-04-14 18:17

„C # 7“ yra nauja „ Tuple sintaksė:

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

Galite jį grąžinti kaip įrašą:

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

Taip pat galite naudoti naują deconstructor sintaksę:

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

Būkite atsargūs su serializacija, bet visa tai yra sintaksinis cukrus - pačiame kompiliuojamame kode bus Tupel<string, int> (kaip ir priimtu atsakymu ) su Item1 ir 2 elementais vietoj foo ir bar . Tai reiškia, kad serializacija (arba de-serializacija) naudos šiuos nuosavybės pavadinimus.

Taigi serializacijai mes paskelbiame įrašų klasę ir ją grąžinsime.

Taip pat naujas „C # 7“ yra patobulintas out parametras. Dabar galite paskelbti integruotą eilutę, kuri geriau tinka kai kuriems kontekstams:

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

Tačiau dažniausiai tai naudosite savo .NET bibliotekose, o ne savo funkcijose.

8
09 марта '17 в 14:43 2017-03-09 14:43 atsakymą pateikė „ Keith“ kovo 9 d. 17 d. 14:43 2017-03-09 14:43

Kai kurie iš šių atsakymų rodo, kad naudojate parametrą „ out“ , tačiau rekomenduoju jį nenaudoti, nes jie neveikia su asinchroniniais metodais . Daugiau informacijos rasite.

Kiti atsakymai suformuluoti naudojant „Tuple“, kurį norėčiau rekomenduoti, bet naudojant naują funkciją, įvestą 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}."); 

Daugiau informacijos rasite čia .

7
27 авг. Luis Teijon atsakymas, rugpjūčio 27 d 2016-08-27 19:24 '16 at 19:24 2016-08-27 19:24

Galite išbandyti šį „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); 

Išeiti:

Rezultatai: 1, 2

6
06 марта '12 в 13:53 2012-03-06 13:53 atsakymą pateikė Rikin Patel kovo 6 d. 12 val. 1:53 2012-03-06 13:53

Klasėse, struktūrose, kolekcijose ir masyvuose gali būti kelios vertės. Funkcijoje taip pat galima nustatyti išėjimo ir atskaitos parametrus. Dinamines ir funkcines kalbas galima grąžinti naudojant kelias vertes, bet ne C #.

5
14 апр. Jose Basilio atsakymas 14 Bal 2009-04-14 18:16 '09, 18:16 PM 2009-04-14 18:16

Štai Two pagrindiniai metodai:

1) „ out “ kaip parametro naudojimas Galite naudoti „išvestį“ versijoms 4.0 ir neesminėms versijoms.

Pavyzdys „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(); } } } 

Išvada:

Stačiakampis plotas - 20

Stačiakampio perimetras yra 18 mm

* Pastaba: * out key apibūdina parametrus, kurių faktinė kintamųjų vieta nukopijuojama į skambinančio metodo kaminą, kur tos pačios vietos gali būti perrašomos. Tai reiškia, kad skambinantysis turės prieigą prie pakeisto parametro.

2) Tuple<T>

Pavyzdžių rinkinys:

Grąžinti kelias „DataType“ reikšmes „ 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 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); } } } 

Išeiti

 perl java c# 1 2 3 

PASTABA. Sistemos naudojimas iš tiesų yra iš 4.0 ir aukštesnės versijos . Tuple tipas yra class . Jis bus skiriamas atskiroje vietoje valdomoje atmintyje. Kuriant „ Tuple , negalite pakeisti fields reikšmių. Tai leidžia Tuple labiau kaip struct .

4
20 сент. atsakymas pateikiamas SHEKHAR SHETE 20 sep . 2013-09-20 09:41 '13 ne 9:41 2013-09-20 09:41

Iš esmės yra du būdai. 1. Naudokite parametrus / ref 2. Grąžinkite objektų masyvą

4
14 апр. Atsakymą pateikė blitzkriegz balandžio 14 d 2009-04-14 18:51 '09 at 18:51 PM 2009-04-14 18:51

Metodas, kuriuo priimamas delegatas, gali suteikti skambinančiam asmeniui kelias reikšmes. Tai užtrunka nuo mano atsakymo čia ir naudojasi priimtais Hadas atsakymais .

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

Abonentai teikia lambda (arba pavadintą funkciją), o intellisense padeda nukopijuoti kintamųjų vardus iš delegato.

 GetMultipleValues((upVotes, comments) => { Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments."); }); 
3
11 сент. Atsakymą pateikė Scott Turner, rugsėjo 11 d 2015-09-11 08:56 '15 at 8:56 2015-09-11 08:56

Šiame straipsnyje galite naudoti tris pasirinktis kaip aukščiau pateiktus pranešimus.

KeyValuePair yra greičiausias būdas.

antrajame.

Vardas yra lėčiausias.

Bet kuriuo atveju tai priklauso nuo to, kas geriausiai tinka jūsų scenarijai.

2
23 нояб. atsakymas pateikiamas maoyang 23 d 2015-11-23 23:15 '15, 23:15, 2015-11-23 23:15

Galite naudoti dinaminį objektą. Manau, kad jis geriau suprantamas nei 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; } 
2
27 мая '16 в 17:24 2016-05-27 17:24 atsakymas pateikiamas Ogge gegužės 27, 16, 17:24 2016-05-27 17:24

Tiesiog naudokite tokią klasę OOP:

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

Nario funkcija grąžina koeficientą, kurį daugumai skambučių iš esmės nurodo. Be to, likusi dalis saugoma kaip duomenų narys, kuris vėliau yra lengvai prieinamas skambintojui.

Taigi, galite turėti daug papildomų „grąžinimo verčių“, labai naudingų, jei diegiate duomenų bazes ar tinklo skambučius, kur jums gali prireikti daug klaidų pranešimų, bet tik esant klaidai.

Aš taip pat įvediau šį klausimą C + +, kurį OP nurodo.

2
21 нояб. Rolando atsakymas lapkričio 21 d. 2014-11-21 13:32 '14, 13:32 2014-11-21 13:32

Kaip tai padaryti:

1) KeyValuePair (geriausias našumas - 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) iš (1,64 ns) arba 4) Sukurkite savo klasę / struktūrą

ns → nanosekundės

Nuoroda: daugkartinio grąžinimo vertės .

1
28 авг. atsakymą pateikė Adham Sabry 28 rug. 2015-08-28 00:46 '15 - 0:46 2015-08-28 00:46

Būsimoje „C #“ versijoje bus įvardyti pavadinimai. Pažvelkite į šią sesiją 9 demo adresu https://channel9.msdn.com/Events/Build/2016/B889

Peršokti į 13:00, jei norite. Tai leis naudoti tokius dalykus kaip:

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

(neišsamus vaizdo pavyzdys)

1
28 июня '16 в 11:23 2016-06-28 11:23 Atsakymą pateikė Niels birželio 28 d. 16 val. 11:23 2016-06-28 11:23

Taip pat galite naudoti „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; } 
0
13 сент. Atsakymas pateikiamas Ruan 13 Sep. 2016-09-13 15:21 '16 at 15:21 pm 2016-09-13 15:21
 <--Return more statements like this you can --> public (int,string,etc) Sample( int a, int b) { //your code; return (a,b); } 

Galite gauti kodą

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

Tikimės, kad tai veikia.

0
18 янв. atsakymas duotas cruzier 18 jan. 2019-01-18 07:30 '19 , 7:30, 2019-01-18 07:30

galite jį išbandyti

 public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } 
0
16 авг. atsakymas pateikiamas IMMORTAL 16 rug. 2013-08-16 12:38 '13, 12:38, 2013-08-16 12:38

Šiandien programuotojams reikia laiko ir nepamirštamų metodų. Paprastas, darbingas ir greitas sprendimas:

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

Naudokite jį kažkur;

 int sum = SumAndSub(20, 5)[0]; int sub = SumAndSub(20, 5)[1]; 
-3
25 сент. atsakymas pateikiamas aliesTech 25 Sep. 2018-09-25 22:47 '18, 10:47 val. 2018-09-25 22:47

Kiti klausimai apie žymes arba Užduoti klausimą