ฉันอ่านคำถามนี้ในเวอร์ชัน C ++แต่ไม่เข้าใจจริงๆ
ใครช่วยอธิบายได้อย่างชัดเจนว่ามันสามารถทำได้และอย่างไร
ฉันอ่านคำถามนี้ในเวอร์ชัน C ++แต่ไม่เข้าใจจริงๆ
ใครช่วยอธิบายได้อย่างชัดเจนว่ามันสามารถทำได้และอย่างไร
คำตอบ:
ใน C # 7 ขึ้นไปดูคำตอบนี้
ในเวอร์ชันก่อนหน้าคุณสามารถใช้. NET 4.0 + ของ Tuple :
ตัวอย่างเช่น:
public Tuple<int, int> GetMultipleValue()
{
return Tuple.Create(1,2);
}
สิ่งอันดับที่มีสองค่ามีItem1
และItem2
เป็นคุณสมบัติ
public (int sum, int count) GetMultipleValues() { return (1, 2); }
ตัวอย่างนี้ถูกนำมาจากตัวอย่างหัวข้อเอกสารของเราเกี่ยวกับเรื่องนี้
เมื่อ C # 7 เปิดตัวแล้วคุณสามารถใช้ไวยากรณ์ Tuples ที่รวมมาใหม่ได้
(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}.");
คุณยังสามารถให้ชื่อองค์ประกอบของคุณ (ดังนั้นจึงไม่ใช่ "Item1", "Item2" เป็นต้น) คุณสามารถทำได้โดยเพิ่มชื่อลงในลายเซ็นหรือวิธีการส่งคืน:
(string first, string middle, string last) LookupName(long id) // tuple elements have names
หรือ
return (first: first, middle: middle, last: last); // named tuple elements in a literal
พวกเขายังสามารถแยกชิ้นส่วนซึ่งเป็นคุณสมบัติใหม่ที่ดีงาม:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
ลองดูลิงค์นี้เพื่อดูตัวอย่างเพิ่มเติมเกี่ยวกับสิ่งที่สามารถทำได้ :)
คุณสามารถใช้สามวิธีที่แตกต่างกัน
1. พารามิเตอร์อ้างอิง / ออก
ใช้การอ้างอิง:
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;
}
ใช้ออก:
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:
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;
}
ใช้คลาส:
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
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;
}
สิ่งอันดับ # 7
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);
}
คุณไม่สามารถทำได้ใน C # สิ่งที่คุณสามารถทำได้คือมีout
พารามิเตอร์หรือส่งคืนคลาสของคุณเอง (หรือ struct หากคุณต้องการให้ไม่เปลี่ยนรูป)
public int GetDay(DateTime date, out string name)
{
// ...
}
การใช้คลาสที่กำหนดเอง (หรือ struct)
public DayOfWeek GetDay(DateTime date)
{
// ...
}
public class DayOfWeek
{
public int Day { get; set; }
public string Name { get; set; }
}
async
วิธีการ Tuple
เป็นวิธีที่จะไป (ผมใช้out
พารามิเตอร์ในการดำเนินการซิงโครแม้ว่าพวกเขาจะมีประโยชน์ในกรณีดังกล่าวแน่นอน.)
หากคุณหมายถึงการคืนค่าหลายค่าคุณสามารถส่งคืนคลาส / โครงสร้างที่มีค่าที่คุณต้องการส่งคืนหรือใช้คำหลัก "ออก" ในพารามิเตอร์ของคุณเช่น:
public void Foo(int input, out int output1, out string output2, out string errors) {
// set out parameters inside function
}
โปสเตอร์ก่อนหน้านี้ถูกต้อง คุณไม่สามารถคืนค่าหลายค่าจากวิธี C # อย่างไรก็ตามคุณมีตัวเลือกสองทาง:
ข้อดีและข้อเสียที่นี่มักจะยากที่จะคิดออก ถ้าคุณคืนค่าโครงสร้างตรวจสอบให้แน่ใจว่ามันมีขนาดเล็กเพราะ structs เป็นประเภทค่าและส่งผ่านไปยังสแต็ก หากคุณส่งคืนอินสแตนซ์ของคลาสมีรูปแบบการออกแบบบางส่วนที่นี่ที่คุณอาจต้องการใช้เพื่อหลีกเลี่ยงปัญหา - สมาชิกของคลาสสามารถแก้ไขได้เนื่องจาก C # ส่งผ่านวัตถุโดยการอ้างอิง (คุณไม่มี ByVal เหมือนที่คุณทำใน VB )
ในที่สุดคุณสามารถใช้พารามิเตอร์เอาต์พุต แต่ฉันจะ จำกัด การใช้สิ่งนี้กับสถานการณ์เมื่อคุณมีเพียงไม่กี่พารามิเตอร์ (เช่น 3 หรือน้อยกว่า) - ไม่อย่างนั้นสิ่งต่าง ๆ น่าเกลียดและยากที่จะรักษา นอกจากนี้การใช้พารามิเตอร์เอาต์พุตอาจเป็นตัวยับยั้งความคล่องตัวเนื่องจากลายเซ็นวิธีการของคุณจะต้องเปลี่ยนทุกครั้งที่คุณต้องการเพิ่มบางสิ่งบางอย่างในค่าส่งคืนในขณะที่ส่งคืนโครงสร้างหรืออินสแตนซ์คลาสคุณสามารถเพิ่มสมาชิกโดยไม่ต้องแก้ไข
จากมุมมองทางสถาปัตยกรรมฉันขอแนะนำให้ใช้คู่หรือคีย์ - ค่าพจนานุกรม ฉันพบว่ารูปแบบการเข้ารหัสนี้ต้องการ "ความรู้ลับ" ในรหัสที่ใช้วิธีนี้ ต้องทราบล่วงหน้าว่ากุญแจจะเป็นอย่างไรและคุณค่าหมายถึงอะไรและหากนักพัฒนาที่ทำงานเกี่ยวกับการใช้งานภายในเปลี่ยนแปลงวิธีการสร้างพจนานุกรมหรือ KVP มันจะสามารถสร้างความล้มเหลวได้อย่างง่ายดายตลอดทั้งแอปพลิเคชัน
Exception
ถ้าค่าที่สองที่คุณต้องการคืนนั้นแยกออกจากค่าแรก: เช่นเมื่อคุณต้องการคืนค่าที่ประสบความสำเร็จหรือมูลค่าที่ไม่ประสบความสำเร็จ
คุณจะกลับมาเป็นเช่นชั้นหรือใช้ออกพารามิเตอร์ นี่คือตัวอย่างของพารามิเตอร์ out:
void mymethod(out int param1, out int param2)
{
param1 = 10;
param2 = 20;
}
เรียกว่าเป็นแบบนี้:
int i, j;
mymethod(out i, out j);
// i will be 20 and j will be 10
มีหลายวิธี; แต่ถ้าคุณไม่ต้องการสร้างวัตถุหรือโครงสร้างใหม่หรืออะไรทำนองนี้คุณสามารถทำเช่นนี้ได้หลังจาก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");
}
ใน C # 7 มีTuple
ไวยากรณ์ใหม่:
static (string foo, int bar) GetTuple()
{
return ("hello", 5);
}
คุณสามารถส่งคืนสิ่งนี้เป็นบันทึก:
var result = GetTuple();
var foo = result.foo
// foo == "hello"
คุณยังสามารถใช้ไวยากรณ์ deconstructor ใหม่:
(string foo) = GetTuple();
// foo == "hello"
ระมัดระวังกับอนุกรม แต่ทั้งหมดนี้เป็นน้ำตาลประโยค - ในรหัสเรียบเรียงจริงนี้จะเป็นTuple<string, int>
(เป็นต่อคำตอบที่ได้รับการยอมรับ ) ด้วยItem1
และItem2
แทนและfoo
bar
นั่นหมายความว่าการทำให้เป็นอนุกรม (หรือดีซีเรียลไลเซชั่น) จะใช้ชื่อคุณสมบัติเหล่านั้นแทน
ดังนั้นสำหรับการทำให้เป็นอนุกรมประกาศคลาสเรกคอร์ดและส่งคืนนั้นแทน
ใหม่ใน C # 7 เป็นไวยากรณ์ที่ปรับปรุงสำหรับout
พารามิเตอร์ ตอนนี้คุณสามารถประกาศout
อินไลน์ซึ่งเหมาะกว่าในบางบริบท:
if(int.TryParse("123", out int result)) {
// Do something with result
}
อย่างไรก็ตามส่วนใหญ่คุณจะใช้สิ่งนี้ในห้องสมุดของ. NET แทนที่จะเป็นหน้าที่ของคุณเอง
บางคำตอบแนะนำให้ใช้พารามิเตอร์หมดแต่ฉันไม่แนะนำให้ใช้เนื่องจากไม่สามารถใช้กับวิธีการแบบอะซิงโครนัสได้ ดู สิ่งนี้สำหรับข้อมูลเพิ่มเติม
คำตอบอื่น ๆ ที่ระบุไว้โดยใช้ Tuple ซึ่งฉันอยากจะแนะนำเช่นกัน แต่การใช้คุณสมบัติใหม่ที่แนะนำใน 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}.");
มีหลายวิธีในการทำเช่นนี้ คุณสามารถใช้ref
พารามิเตอร์:
int Foo(ref Bar bar) { }
สิ่งนี้ผ่านการอ้างอิงไปยังฟังก์ชันดังนั้นจึงอนุญาตให้ฟังก์ชันแก้ไขวัตถุในสแต็กของรหัสโทรศัพท์ ในขณะที่นี่ไม่ใช่ในทางเทคนิคค่า "คืน" มันเป็นวิธีที่จะมีฟังก์ชั่นทำสิ่งที่คล้ายกัน ในโค้ดข้างต้นฟังก์ชั่นจะกลับint
และ (อาจ) bar
ปรับเปลี่ยน
อีกวิธีที่คล้ายกันคือการใช้out
พารามิเตอร์ out
พารามิเตอร์เป็นเหมือนกันกับref
พารามิเตอร์ที่มีการเพิ่มเติมกฎบังคับใช้คอมไพเลอร์ กฎนี้คือถ้าคุณส่งout
พารามิเตอร์ไปยังฟังก์ชั่นฟังก์ชั่นนั้นจะต้องตั้งค่าของมันก่อนที่จะกลับมา นอกเหนือจากกฎนั้นout
พารามิเตอร์ทำงานเหมือนref
พารามิเตอร์
วิธีสุดท้าย (และดีที่สุดในกรณีส่วนใหญ่) คือการสร้างประเภทที่ห่อหุ้มค่าทั้งสองและอนุญาตให้ฟังก์ชั่นเพื่อกลับไปที่:
class FooBar
{
public int i { get; set; }
public Bar b { get; set; }
}
FooBar Foo(Bar bar) { }
วิธีการขั้นสุดท้ายนี้ง่ายขึ้นและง่ายต่อการอ่านและทำความเข้าใจ
ไม่คุณไม่สามารถส่งคืนค่าหลายค่าจากฟังก์ชั่นใน C # (สำหรับรุ่นที่ต่ำกว่า C # 7) อย่างน้อยก็ไม่ใช่วิธีที่คุณสามารถทำได้ใน Python
อย่างไรก็ตามมีทางเลือกสองทาง:
คุณสามารถส่งคืนอาเรย์ของวัตถุประเภทด้วยค่าหลายค่าที่คุณต้องการ
private object[] DoSomething()
{
return new [] { 'value1', 'value2', 3 };
}
คุณสามารถใช้out
พารามิเตอร์
private string DoSomething(out string outparam1, out int outparam2)
{
outparam1 = 'value2';
outparam2 = 3;
return 'value1';
}
ใน C # 4 คุณจะสามารถใช้การสนับสนุนในตัวสำหรับสิ่งอันดับเพื่อจัดการสิ่งนี้ได้อย่างง่ายดาย
ในขณะเดียวกันมีสองตัวเลือก
ก่อนอื่นคุณสามารถใช้พารามิเตอร์ ref หรือ out เพื่อกำหนดค่าให้กับพารามิเตอร์ของคุณซึ่งจะถูกส่งกลับไปยังรูทีนการเรียก
ดูเหมือนว่า:
void myFunction(ref int setMe, out int youMustSetMe);
ประการที่สองคุณสามารถสรุปค่าที่ส่งคืนของคุณลงในโครงสร้างหรือคลาสแล้วส่งกลับเป็นสมาชิกของโครงสร้างนั้น KeyValuePair ทำงานได้ดีสำหรับ 2 - สำหรับมากกว่า 2 คุณจะต้องมีคลาสหรือโครงสร้างแบบกำหนดเอง
คุณสามารถลองใช้ "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);
ผลผลิต:
ผลลัพธ์: 1, 2
คลาสโครงสร้างคอลเลกชันและอาร์เรย์สามารถมีหลายค่า พารามิเตอร์เอาต์พุตและการอ้างอิงยังสามารถตั้งค่าในฟังก์ชั่น คืนค่าหลายค่าเป็นไปได้ในภาษาแบบไดนามิกและฟังก์ชั่นการทำงานโดยวิธีการ tuples แต่ไม่ได้อยู่ใน C #
ส่วนใหญ่มีสองวิธี 1. ใช้พารามิเตอร์ out / ref 2. ส่งคืนอาเรย์ของวัตถุ
นี่คือพื้นฐาน Two
วิธีการ :
1) การใช้ ' out
' เป็นพารามิเตอร์
คุณสามารถใช้ 'ออก' สำหรับทั้งรุ่น 4.0 และรุ่นรองได้เช่นกัน
ตัวอย่างของ 'ออก':
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();
}
}
}
เอาท์พุท:
พื้นที่สี่เหลี่ยมผืนผ้าคือ 20
ปริมณฑลของสี่เหลี่ยมผืนผ้าคือ 18
* หมายเหตุ: * out
-keyword อธิบายพารามิเตอร์ที่มีตำแหน่งตัวแปรจริงถูกคัดลอกไปยังสแต็คของวิธีการที่เรียกซึ่งสามารถเขียนตำแหน่งเดียวกันได้ ซึ่งหมายความว่าวิธีการโทรจะเข้าถึงพารามิเตอร์ที่เปลี่ยนแปลง
2) Tuple<T>
ตัวอย่างของ Tuple:
คืนค่า DataType หลายค่าโดยใช้ 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);
}
}
}
เอาท์พุต
perl
java
c#
1
2
3
หมายเหตุ: การ ใช้ Tuple นั้นถูกต้องจาก Framework 4.0 ขึ้นไป ประเภทเป็นTuple
class
มันจะถูกจัดสรรในตำแหน่งแยกต่างหากบนฮีปที่มีการจัดการในหน่วยความจำ เมื่อคุณสร้างคุณไม่สามารถเปลี่ยนค่าของมันTuple
fields
นี้จะทำให้มากขึ้นเช่นTuple
struct
<--Return more statements like this you can -->
public (int,string,etc) Sample( int a, int b)
{
//your code;
return (a,b);
}
คุณสามารถรับรหัสเช่น
(c,d,etc) = Sample( 1,2);
ฉันหวังว่ามันจะได้ผล
วิธีการผู้รับมอบสิทธิ์สามารถให้ค่าหลายค่าแก่ผู้โทร ขอยืมนี้จากคำตอบของฉันที่นี่และใช้นิด ๆ หน่อย ๆ จากคำตอบที่ได้รับการยอมรับของ Hadas
delegate void ValuesDelegate(int upVotes, int comments);
void GetMultipleValues(ValuesDelegate callback)
{
callback(1, 2);
}
ผู้โทรจัดเตรียมแลมบ์ดา (หรือฟังก์ชั่นที่ตั้งชื่อไว้) และความช่วยเหลือในการจัดเก็บข้อมูลด้วยการคัดลอกชื่อตัวแปรจากผู้รับมอบสิทธิ์
GetMultipleValues((upVotes, comments) =>
{
Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments.");
});
เพียงใช้ในลักษณะ OOP คลาสเช่นนี้:
class div
{
public int remainder;
public int quotient(int dividend, int divisor)
{
remainder = ...;
return ...;
}
}
ฟังก์ชั่นสมาชิกส่งกลับความฉลาดทางที่ผู้โทรส่วนใหญ่มีความสนใจเป็นหลักนอกจากนี้มันจะเก็บส่วนที่เหลือเป็นสมาชิกข้อมูลซึ่งผู้โทรสามารถเข้าถึงได้ง่ายในภายหลัง
วิธีนี้คุณสามารถมี "คืนค่า" เพิ่มเติมมีประโยชน์มากถ้าคุณใช้การเรียกฐานข้อมูลหรือเครือข่ายซึ่งอาจต้องใช้ข้อความแสดงข้อผิดพลาดจำนวนมาก แต่ในกรณีที่เกิดข้อผิดพลาดเท่านั้น
ฉันป้อนโซลูชันนี้ในคำถาม C ++ ที่ OP อ้างถึง
จากนี้บทความคุณสามารถใช้สามตัวเลือกเป็นโพสต์ที่กล่าวข้างต้น
KeyValuePairเป็นวิธีที่รวดเร็วที่สุด
ออกเป็นที่สอง
Tupleนั้นช้าที่สุด
อย่างไรก็ตามสิ่งนี้ขึ้นอยู่กับสิ่งที่ดีที่สุดสำหรับสถานการณ์ของคุณ
รุ่นในอนาคตของ C # จะรวมชื่อ tuples ดูที่เซสชั่น channel9 นี้สำหรับการสาธิต https://channel9.msdn.com/Events/Build/2016/B889
ข้ามไปที่ 13:00 สำหรับสิ่ง tuple สิ่งนี้จะอนุญาต:
(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}
int resultsum = Tally(numbers).sum
(ตัวอย่างที่ไม่สมบูรณ์จากวิดีโอ)
คุณสามารถใช้วัตถุแบบไดนามิก ฉันคิดว่ามันอ่านง่ายกว่า 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;
}
วิธีที่จะทำ:
1) KeyValuePair (ประสิทธิภาพที่ดีที่สุด - 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) หรือ ref 4) สร้าง class / struct ของคุณเอง
ns -> nanoseconds
คุณสามารถลองสิ่งนี้
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
yield return "value1"; yield return "value2";
เพื่อไม่ต้องสร้างใหม่อย่างชัดเจนstring[]
?
คุณยังสามารถใช้ 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;
}
คำตอบอย่างรวดเร็วเป็นพิเศษสำหรับประเภทอาร์เรย์คืน:
private int[] SumAndSub(int A, int B)
{
return new[] { A + B, A - B };
}
โดยใช้:
var results = SumAndSub(20, 5);
int sum = results[0];
int sub = results[1];