मैंने इस प्रश्न का C ++ संस्करण पढ़ा, लेकिन वास्तव में इसे समझ नहीं पाया।
क्या कोई स्पष्ट रूप से समझा सकता है कि क्या यह किया जा सकता है और कैसे?
मैंने इस प्रश्न का C ++ संस्करण पढ़ा, लेकिन वास्तव में इसे समझ नहीं पाया।
क्या कोई स्पष्ट रूप से समझा सकता है कि क्या यह किया जा सकता है और कैसे?
जवाबों:
C # 7 और इसके बाद के संस्करण में, यह उत्तर देखें ।
पिछले संस्करणों में, आप .NET 4.0 + का उपयोग कर सकते हैं :
उदाहरण के लिए:
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}.");
आप अपने तत्वों को नाम भी प्रदान कर सकते हैं (इसलिए वे "आइटम 1", "आइटम 2" आदि नहीं हैं)। आप इसे हस्ताक्षर या रिटर्न विधियों में नाम जोड़कर कर सकते हैं:
(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 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. टप्पल
टपल क्लास
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
पैरामीटर है या अपनी खुद की कक्षा (या यदि आप चाहते हैं कि यह अपरिवर्तनीय हो) को वापस कर दें।
public int GetDay(DateTime date, out string name)
{
// ...
}
कस्टम वर्ग (या संरचना) का उपयोग करना
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 # विधि से कई मान नहीं लौटा सकते। हालाँकि, आपके पास कुछ विकल्प हैं:
यहाँ पेशेवरों और विपक्ष अक्सर यह पता लगाने के लिए मुश्किल है। यदि आप एक संरचना लौटाते हैं, तो सुनिश्चित करें कि यह छोटा है क्योंकि संरचना मूल्य प्रकार है और स्टैक पर पारित किया गया है। यदि आप किसी कक्षा का एक उदाहरण देते हैं, तो कुछ डिज़ाइन पैटर्न यहाँ दिए गए हैं, जिनका उपयोग आप समस्याओं के कारण से बचने के लिए कर सकते हैं - कक्षाओं के सदस्यों को संशोधित किया जा सकता है क्योंकि C # संदर्भ द्वारा ऑब्जेक्ट पास करता है (आपके पास ByVal नहीं है जैसे आपने VB में किया था। )।
अंत में आप आउटपुट मापदंडों का उपयोग कर सकते हैं, लेकिन मैं इसके उपयोग को परिदृश्यों तक सीमित कर दूंगा जब आपके पास केवल कुछ जोड़े (जैसे 3 या उससे कम) पैरामीटर होंगे - अन्यथा चीजें बनाए रखने के लिए बदसूरत और कठिन हो जाती हैं। इसके अलावा, आउटपुट मापदंडों का उपयोग चपलता के लिए एक अवरोधक हो सकता है क्योंकि आपके विधि हस्ताक्षर को हर बार आपको बदले मूल्य में कुछ जोड़ने की आवश्यकता होगी, जबकि एक संरचना या वर्ग का उदाहरण देते हुए आप विधि हस्ताक्षर को संशोधित किए बिना सदस्यों को जोड़ सकते हैं।
एक वास्तुकला के दृष्टिकोण से, मैं कुंजी-मूल्य जोड़े या शब्दकोशों का उपयोग करने के खिलाफ सिफारिश करूंगा। मुझे लगता है कि कोडिंग की इस शैली को कोड में "गुप्त ज्ञान" की आवश्यकता होती है जो विधि का उपभोग करता है। यह समय से पहले पता होना चाहिए कि चाबियाँ क्या होने जा रही हैं और मूल्यों का क्या मतलब है और अगर आंतरिक कार्यान्वयन पर काम करने वाला डेवलपर शब्दकोश या केवीपी बनाने के तरीके को बदलता है, तो यह आसानी से पूरे एप्लिकेशन में विफलता कास्केड बना सकता है।
Exception
यदि दूसरा मूल्य जिसे आप वापस करना चाहते हैं, पहले से ही अलग है: जैसे कि जब आप या तो एक प्रकार का सफल मान लौटना चाहते हैं, या एक प्रकार का असफल मूल्य।
आप या तो एक श्रेणी उदाहरण वापस करते हैं या मापदंडों का उपयोग करते हैं। यहाँ बाहर मापदंडों का एक उदाहरण है:
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"
आप नए डिकंस्ट्रक्टर सिंटैक्स का भी उपयोग कर सकते हैं:
(string foo) = GetTuple();
// foo == "hello"
तथापि क्रमबद्धता से सावधान रहें, यह सब वाक्यात्मक चीनी है - वास्तविक संकलित कोड में यह हो जाएगा एक Tuple<string, int>
(के रूप में स्वीकार किए जाते हैं जवाब प्रति ) के साथ Item1
और Item2
के बजाय foo
और bar
। इसका मतलब है कि क्रमांकन (या deserialisation) इसके बजाय उन संपत्ति नामों का उपयोग करेगा।
इसलिए, क्रमबद्धता के लिए एक रिकॉर्ड क्लास घोषित करें और उसके बजाय वापस लौटें।
सी # 7 में भी नया out
पैरामीटर के लिए एक बेहतर सिंटैक्स है । अब आप out
इनलाइन घोषित कर सकते हैं , जो कुछ संदर्भों में बेहतर है:
if(int.TryParse("123", out int result)) {
// Do something with result
}
हालाँकि, ज्यादातर आप अपने स्वयं के कार्यों के बजाय .NET के स्वयं के पुस्तकालयों में इसका उपयोग करेंगे।
कुछ जवाब मापदंडों का उपयोग करने का सुझाव देते हैं, लेकिन मैं सलाह देता हूं कि वे इस का उपयोग न करें क्योंकि वे एसिंक्स विधियों के साथ काम नहीं करते हैं । अधिक जानकारी के लिए इसे देखें ।
ट्यूपल का उपयोग करते हुए अन्य उत्तर दिए गए हैं, जिन्हें मैं भी सुझाऊंगा लेकिन 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 से कम संस्करणों के लिए), कम से कम उस तरीके से नहीं जैसे आप इसे पायथन में कर सकते हैं।
हालाँकि, कुछ विकल्प हैं:
आप इसमें इच्छित कई मानों के साथ एक प्रकार की वस्तु वापस कर सकते हैं।
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 में, आप इसे आसानी से संभालने के लिए ट्यूपल्स के लिए अंतर्निहित समर्थन का उपयोग करने में सक्षम होंगे।
इस बीच, दो विकल्प हैं।
सबसे पहले, आप अपने मापदंडों को मान असाइन करने के लिए रेफरी या आउट पैरामीटर का उपयोग कर सकते हैं, जो कॉलिंग रूटीन में वापस पास हो जाते हैं।
ऐसा दिखता है:
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
कक्षाएं, संरचनाएं, संग्रह और सरणी में कई मान हो सकते हैं। आउटपुट और संदर्भ पैरामीटर को एक फ़ंक्शन में भी सेट किया जा सकता है। ट्यूल के माध्यम से गतिशील और कार्यात्मक भाषाओं में कई मान संभव हैं, लेकिन C # में नहीं।
मुख्य रूप से दो विधियाँ हैं। 1. पैरामीटर का उपयोग करें / रेफरी करें। वस्तुओं का एक सरणी लौटें
यहाँ बुनियादी 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
-कीवर्ड उन मापदंडों का वर्णन करता है जिनके वास्तविक चर स्थानों को कॉपी विधि के ढेर पर कॉपी किया जाता है, जहां उन्हीं स्थानों को फिर से लिखा जा सकता है। इसका मतलब है कि कॉलिंग विधि परिवर्तित पैरामीटर तक पहुंच जाएगी।
2) Tuple<T>
टपल का उदाहरण:
एकाधिक डेटा टाइप मान का उपयोग करके लौटना 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 का उपयोग फ्रेमवर्क 4.0 और इसके बाद के संस्करण से मान्य है । Tuple
प्रकार एक है class
। इसे स्मृति में प्रबंधित हीप पर एक अलग स्थान में आवंटित किया जाएगा। एक बार जब आप बना लेते हैं Tuple
, तो आप इसके मूल्यों को नहीं बदल सकते fields
। यह Tuple
एक तरह अधिक बनाता है struct
।
प्रतिनिधि लेने वाली एक विधि कॉलर को कई मान प्रदान कर सकती है। यह मेरे उत्तर से यहाँ उधार लेता है और हाडास के स्वीकृत उत्तर से थोड़ा सा उपयोग करता है ।
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 ++ प्रश्न में भी दर्ज किया जिसका ओपी उल्लेख कर रहा है।
सी # के भविष्य के संस्करण का नाम ट्यूपल्स शामिल करने जा रहा है। डेमो चैनल के लिए इस चैनल पर एक नज़र डालें https://channel9.msdn.com/Events/Build/2016/B889
13:00 के लिए टपल सामान पर जाएं। यह सामान की अनुमति देगा:
(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}
int resultsum = Tally(numbers).sum
(वीडियो से अधूरा उदाहरण)
आप एक गतिशील वस्तु का उपयोग कर सकते हैं। मुझे लगता है कि टपल से बेहतर पठनीयता है।
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 एनएस):
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) टपल - 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) या रेफरी 4) अपनी खुद की कस्टम क्लास / स्ट्रक्चर बनाएं
ns -> नैनोसेकंड
संदर्भ: कई-रिटर्न-मान ।
आप यह कोशिश कर सकते हैं
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];