Saya membaca versi C ++ dari pertanyaan ini tetapi tidak terlalu memahaminya.
Bisakah seseorang tolong jelaskan jika itu bisa dilakukan dan bagaimana caranya?
Saya membaca versi C ++ dari pertanyaan ini tetapi tidak terlalu memahaminya.
Bisakah seseorang tolong jelaskan jika itu bisa dilakukan dan bagaimana caranya?
Jawaban:
Di C # 7 dan di atas, lihat jawaban ini .
Dalam versi sebelumnya, Anda dapat menggunakan Tuple .NET 4.0 + :
Sebagai contoh:
public Tuple<int, int> GetMultipleValue()
{
return Tuple.Create(1,2);
}
Tuple dengan dua nilai memiliki Item1
dan Item2
sebagai properti.
public (int sum, int count) GetMultipleValues() { return (1, 2); }
Contoh ini diambil dari contoh topik Dokumentasi kami tentang ini .
Sekarang setelah C # 7 telah dirilis, Anda dapat menggunakan sintaks Tuples yang baru disertakan
(string, string, string) LookupName(long id) // tuple return type
{
... // retrieve first, middle and last from data storage
return (first, middle, last); // tuple literal
}
yang kemudian bisa digunakan seperti ini:
var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");
Anda juga dapat memberikan nama ke elemen Anda (jadi mereka bukan "Item1", "Item2" dll). Anda dapat melakukannya dengan menambahkan nama ke tanda tangan atau metode pengembalian:
(string first, string middle, string last) LookupName(long id) // tuple elements have names
atau
return (first: first, middle: middle, last: last); // named tuple elements in a literal
Mereka juga dapat didekonstruksi, yang merupakan fitur baru yang cukup bagus:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
Lihat tautan ini untuk melihat lebih banyak contoh tentang apa yang dapat dilakukan :)
Anda dapat menggunakan tiga cara berbeda
1. parameter ref / out
menggunakan referensi:
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;
}
menggunakan:
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 / kelas
menggunakan 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;
}
menggunakan kelas:
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
Kelas 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);
}
Anda tidak dapat melakukan ini dalam C #. Yang dapat Anda lakukan adalah memilikiout
parameter atau mengembalikan kelas Anda sendiri (atau struct jika Anda ingin itu tidak berubah).
public int GetDay(DateTime date, out string name)
{
// ...
}
Menggunakan kelas khusus (atau struct)
public DayOfWeek GetDay(DateTime date)
{
// ...
}
public class DayOfWeek
{
public int Day { get; set; }
public string Name { get; set; }
}
async
metode. Tuple
adalah cara untuk pergi. (Saya menggunakan out
parameter dalam operasi sinkron; mereka memang berguna dalam kasus-kasus itu.)
Jika Anda bermaksud mengembalikan beberapa nilai, Anda dapat mengembalikan kelas / struct yang berisi nilai yang ingin Anda kembalikan, atau menggunakan kata kunci "out" pada parameter Anda, seperti:
public void Foo(int input, out int output1, out string output2, out string errors) {
// set out parameters inside function
}
Poster sebelumnya benar. Anda tidak dapat mengembalikan beberapa nilai dari metode C #. Namun, Anda memiliki beberapa opsi:
Pro dan kontra di sini seringkali sulit dipecahkan. Jika Anda mengembalikan struktur, pastikan itu kecil karena struct adalah tipe nilai dan diteruskan pada stack. Jika Anda mengembalikan instance kelas, ada beberapa pola desain di sini yang mungkin ingin Anda gunakan untuk menghindari masalah - anggota kelas dapat dimodifikasi karena C # melewati objek dengan referensi (Anda tidak memiliki ByVal seperti yang Anda lakukan di VB ).
Akhirnya Anda dapat menggunakan parameter output tetapi saya akan membatasi penggunaan ini untuk skenario ketika Anda hanya memiliki pasangan (seperti 3 atau kurang) parameter - jika tidak semuanya menjadi jelek dan sulit untuk dipelihara. Selain itu, penggunaan parameter output dapat menjadi penghambat kelincahan karena tanda tangan metode Anda harus berubah setiap kali Anda perlu menambahkan sesuatu ke nilai kembali sedangkan mengembalikan contoh struct atau kelas Anda dapat menambahkan anggota tanpa memodifikasi tanda tangan metode.
Dari sudut pandang arsitektur, saya akan merekomendasikan untuk tidak menggunakan pasangan kunci-nilai atau kamus. Saya menemukan gaya pengkodean ini membutuhkan "pengetahuan rahasia" dalam kode yang menggunakan metode ini. Ia harus mengetahui sebelumnya apa yang akan menjadi kunci dan apa nilai-nilai artinya dan jika pengembang bekerja pada implementasi internal mengubah cara kamus atau KVP dibuat, itu bisa dengan mudah membuat kaskade kegagalan di seluruh aplikasi.
Exception
jika nilai kedua yang ingin Anda kembalikan terpisah dari yang pertama: seperti ketika Anda ingin mengembalikan salah satu jenis nilai sukses, atau semacam nilai tidak berhasil.
Anda baik mengembalikan contoh kelas atau menggunakan keluar parameter. Berikut ini contoh parameter keluar:
void mymethod(out int param1, out int param2)
{
param1 = 10;
param2 = 20;
}
Sebut saja seperti ini:
int i, j;
mymethod(out i, out j);
// i will be 20 and j will be 10
Ada banyak cara; tetapi jika Anda tidak ingin membuat Obyek atau struktur baru atau sesuatu seperti ini, Anda dapat melakukannya seperti di bawah ini setelah 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");
}
Di C # 7 Ada Tuple
sintaks baru :
static (string foo, int bar) GetTuple()
{
return ("hello", 5);
}
Anda dapat mengembalikan ini sebagai catatan:
var result = GetTuple();
var foo = result.foo
// foo == "hello"
Anda juga dapat menggunakan sintaks dekonstruktor baru:
(string foo) = GetTuple();
// foo == "hello"
Berhati-hatilah dengan serialisasi, semua ini adalah gula sintaksis - dalam kode terkompilasi yang sebenarnya, ini akan menjadi Tuple<string, int>
( sesuai jawaban yang diterima ) dengan Item1
dan Item2
bukannya foo
dan bar
. Itu berarti bahwa serialisasi (atau deserialisation) akan menggunakan nama-nama properti sebagai gantinya.
Jadi, untuk serialisasi mendeklarasikan kelas rekaman dan mengembalikannya sebagai gantinya.
Juga baru di C # 7 adalah sintaks yang ditingkatkan untuk out
parameter. Anda sekarang dapat mendeklarasikan out
inline, yang lebih cocok dalam beberapa konteks:
if(int.TryParse("123", out int result)) {
// Do something with result
}
Namun, sebagian besar Anda akan menggunakan ini di perpustakaan .NET sendiri, bukan di fungsi Anda sendiri.
Beberapa jawaban menyarankan untuk menggunakan parameter tetapi saya sarankan tidak menggunakan ini karena mereka tidak bekerja dengan metode async . Lihat ini untuk informasi lebih lanjut.
Jawaban lain dinyatakan menggunakan Tuple, yang saya sarankan juga tetapi menggunakan fitur baru yang diperkenalkan di 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}.");
Informasi lebih lanjut dapat ditemukan di sini .
Ada beberapa cara untuk melakukan ini. Anda dapat menggunakan ref
parameter:
int Foo(ref Bar bar) { }
Ini meneruskan referensi ke fungsi sehingga memungkinkan fungsi untuk mengubah objek dalam tumpukan kode panggilan. Meskipun ini bukan nilai "kembali" secara teknis, ini adalah cara agar fungsi melakukan hal yang serupa. Dalam kode di atas fungsi akan mengembalikan int
dan (berpotensi) memodifikasi bar
.
Pendekatan lain yang serupa adalah dengan menggunakan out
parameter. Sebuah out
parameter identik dengan ref
parameter dengan tambahan compiler ditegakkan aturan,. Aturan ini adalah bahwa jika Anda melewatkan out
parameter ke suatu fungsi, fungsi itu diperlukan untuk mengatur nilainya sebelum kembali. Selain aturan itu, out
parameter berfungsi seperti ref
parameter.
Pendekatan terakhir (dan yang terbaik dalam banyak kasus) adalah membuat tipe yang merangkum kedua nilai dan memungkinkan fungsi mengembalikannya:
class FooBar
{
public int i { get; set; }
public Bar b { get; set; }
}
FooBar Foo(Bar bar) { }
Pendekatan akhir ini lebih sederhana dan lebih mudah dibaca dan dipahami.
Tidak, Anda tidak dapat mengembalikan beberapa nilai dari fungsi dalam C # (untuk versi yang lebih rendah dari C # 7), setidaknya tidak dengan cara yang dapat Anda lakukan dengan Python.
Namun, ada beberapa alternatif:
Anda bisa mengembalikan array tipe objek dengan beberapa nilai yang Anda inginkan di dalamnya.
private object[] DoSomething()
{
return new [] { 'value1', 'value2', 3 };
}
Anda dapat menggunakan out
parameter.
private string DoSomething(out string outparam1, out int outparam2)
{
outparam1 = 'value2';
outparam2 = 3;
return 'value1';
}
Di C # 4, Anda akan dapat menggunakan dukungan bawaan untuk tupel untuk menangani ini dengan mudah.
Sementara itu, ada dua opsi.
Pertama, Anda dapat menggunakan parameter ref atau out untuk menetapkan nilai ke parameter Anda, yang akan diteruskan kembali ke rutinitas pemanggilan.
Ini terlihat seperti:
void myFunction(ref int setMe, out int youMustSetMe);
Kedua, Anda bisa membungkus nilai pengembalian Anda ke dalam struktur atau kelas, dan meneruskannya kembali sebagai anggota struktur itu. KeyValuePair berfungsi dengan baik untuk 2 - untuk lebih dari 2 Anda membutuhkan kelas atau struct khusus.
Anda dapat mencoba "KeyValuePair" ini
private KeyValuePair<int, int> GetNumbers()
{
return new KeyValuePair<int, int>(1, 2);
}
var numbers = GetNumbers();
Console.WriteLine("Output : {0}, {1}",numbers.Key, numbers.Value);
Keluaran:
Output: 1, 2
Kelas, Struktur, Koleksi dan Array dapat berisi beberapa nilai. Parameter keluaran dan referensi juga dapat diatur dalam suatu fungsi. Mengembalikan beberapa nilai dimungkinkan dalam bahasa yang dinamis dan fungsional dengan menggunakan tupel, tetapi tidak dalam C #.
Terutama ada dua metode. 1. Gunakan parameter out / ref 2. Kembalikan Array objek
Berikut adalah Two
metode dasar :
1) Penggunaan ' out
' sebagai parameter
Anda dapat menggunakan 'keluar' untuk versi 4.0 dan minor juga.
Contoh 'keluar':
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();
}
}
}
Keluaran:
Luas Persegi Panjang adalah 20
Perimeter Persegi Panjang adalah 18
* Catatan: * out
-keyword menjelaskan parameter yang lokasi variabel aktualnya disalin ke tumpukan metode yang dipanggil, di mana lokasi yang sama dapat ditulis ulang. Ini berarti bahwa metode panggilan akan mengakses parameter yang diubah.
2) Tuple<T>
Contoh Tuple:
Mengembalikan beberapa nilai Tipe Data menggunakan 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);
}
}
}
Keluaran
perl
java
c#
1
2
3
CATATAN: Penggunaan Tuple valid dari Framework 4.0 dan di atasnya . Tuple
tipe adalah a class
. Ini akan dialokasikan di lokasi terpisah pada tumpukan yang dikelola dalam memori. Setelah Anda membuat Tuple
, Anda tidak dapat mengubah nilai-nilainya fields
. Ini membuat Tuple
lebih seperti a struct
.
<--Return more statements like this you can -->
public (int,string,etc) Sample( int a, int b)
{
//your code;
return (a,b);
}
Anda dapat menerima kode seperti
(c,d,etc) = Sample( 1,2);
Saya harap ini berhasil.
Metode mengambil delegasi dapat memberikan beberapa nilai kepada pemanggil. Ini meminjam dari jawaban saya di sini dan menggunakan sedikit dari jawaban Hadas yang diterima .
delegate void ValuesDelegate(int upVotes, int comments);
void GetMultipleValues(ValuesDelegate callback)
{
callback(1, 2);
}
Penelepon menyediakan lambda (atau fungsi bernama) dan intellisense membantu dengan menyalin nama-nama variabel dari delegasi.
GetMultipleValues((upVotes, comments) =>
{
Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments.");
});
Cukup gunakan dengan cara OOP kelas seperti ini:
class div
{
public int remainder;
public int quotient(int dividend, int divisor)
{
remainder = ...;
return ...;
}
}
Anggota fungsi mengembalikan hasil bagi sebagian besar penelepon yang terutama tertarik. Selain itu, anggota fungsi menyimpan sisanya sebagai anggota data, yang mudah diakses oleh penelepon sesudahnya.
Dengan cara ini Anda dapat memiliki banyak "nilai pengembalian" tambahan, sangat berguna jika Anda menerapkan panggilan basis data atau jaringan, di mana banyak pesan kesalahan mungkin diperlukan tetapi hanya jika terjadi kesalahan.
Saya memasukkan solusi ini juga dalam pertanyaan C ++ yang dirujuk OP.
Versi C # yang akan datang akan memasukkan tuple bernama. Lihatlah sesi channel9 ini untuk demo https://channel9.msdn.com/Events/Build/2016/B889
Lompat ke 13:00 untuk hal-hal tuple. Ini akan memungkinkan hal-hal seperti:
(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}
int resultsum = Tally(numbers).sum
(contoh tidak lengkap dari video)
Anda bisa menggunakan objek dinamis. Saya pikir ini memiliki keterbacaan yang lebih baik daripada 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;
}
Cara melakukannya:
1) KeyValuePair (Kinerja Terbaik - 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) keluar (1,64 ns) atau ref 4) Buat kelas / struct khusus Anda sendiri
ns -> nanodetik
Referensi: beberapa-return-nilai .
Anda bisa mencoba ini
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
yield return "value1"; yield return "value2";
karena tidak harus secara eksplisit membuat yang baru string[]
?
Anda juga dapat menggunakan 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;
}
Jawaban cepat khusus untuk pengembalian tipe array:
private int[] SumAndSub(int A, int B)
{
return new[] { A + B, A - B };
}
Menggunakan:
var results = SumAndSub(20, 5);
int sum = results[0];
int sub = results[1];