c# - मैं सी#में किसी फ़ंक्शन से एकाधिक मान कैसे वापस कर सकता हूं?




function return (16)

मैंने इस प्रश्न के सी ++ संस्करण को पढ़ा लेकिन वास्तव में इसे समझ में नहीं आया।

क्या कोई स्पष्ट रूप से समझा सकता है अगर यह किया जा सकता है और कैसे?


इनमें से कुछ उत्तरों ने कहा कि पैरामीटर का उपयोग करें, लेकिन मैं इस का उपयोग न करने की अनुशंसा करता हूं क्योंकि वे async विधियों के साथ काम नहीं करते हैं । अधिक जानकारी के लिए this देखें।

अन्य उत्तरों ने टुपल का उपयोग करके कहा, जिसे मैं भी अनुशंसा करता हूं लेकिन सी # 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}.");

और जानकारी here मिल सकती here


अब सी # 7 जारी किया गया है, आप शामिल नए टुपल्स वाक्यविन्यास का उपयोग कर सकते हैं

(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

क्या किया जा सकता है पर अधिक उदाहरण देखने के लिए इस लिंक को देखें :)


आप इसे आजमा सकते हैं

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

आप इसे सी # में नहीं कर सकते हैं। आप क्या कर सकते हैं 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; }
}

आप एक गतिशील वस्तु का उपयोग कर सकते हैं। मुझे लगता है कि यह ट्यूपल की तुलना में बेहतर पठनीयता है।

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. पैरामीटर को रेफ / आउट करें

रेफरी का उपयोग करना:

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

इसे करने बहुत सारे तरीके हैं। आप ref पैरामीटर का उपयोग कर सकते हैं:

int Foo(ref Bar bar) { }

यह फ़ंक्शन के संदर्भ को पास करता है जिससे फ़ंक्शन को कॉलिंग कोड के ढेर में ऑब्जेक्ट को संशोधित करने की इजाजत मिलती है। हालांकि यह तकनीकी रूप से "लौटा" मूल्य नहीं है, यह एक ऐसा काम करने का एक तरीका है जो कुछ ऐसा करता है। फ़ंक्शन के ऊपर दिए गए कोड में एक int और (संभावित रूप से) संशोधित bar वापस आ जाएगा।

एक और समान दृष्टिकोण एक out पैरामीटर का उपयोग करना out । एक out पैरामीटर एक अतिरिक्त, कंपाइलर लागू नियम के साथ एक ref पैरामीटर के समान है। यह नियम यह है कि यदि आप फ़ंक्शन में out पैरामीटर पास करते हैं, तो उस फ़ंक्शन को लौटने से पहले अपना मान सेट करना आवश्यक है। उस नियम के अलावा, एक out पैरामीटर एक ref पैरामीटर की तरह काम करता है।

अंतिम दृष्टिकोण (और अधिकांश मामलों में सबसे अच्छा) एक ऐसा प्रकार बनाना है जो दोनों मानों को समाहित करता है और फ़ंक्शन को वापस करने की अनुमति देता है:

class FooBar 
{
    public int i { get; set; }
    public Bar b { get; set; }
}

FooBar Foo(Bar bar) { }

यह अंतिम दृष्टिकोण पढ़ने और समझने के लिए सरल और आसान है।


एक प्रतिनिधि लेने का एक तरीका कॉलर को कई मूल्य प्रदान कर सकता है। यह मेरे उत्तर से here उधार लेता here और हदास के स्वीकृत उत्तर से थोड़ा सा उपयोग करता है।

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

ओओपी तरीके से इस तरह की कक्षा में बस उपयोग करें:

class div
{
    public int remainder;

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

फ़ंक्शन सदस्य उस भाग को वापस लौटाता है जो अधिकतर कॉलर्स मुख्य रूप से रुचि रखते हैं। इसके अतिरिक्त यह शेष को डेटा सदस्य के रूप में संग्रहीत करता है, जिसे बाद में कॉलर द्वारा आसानी से पहुंचा जा सकता है।

इस तरह आप कई अतिरिक्त "वापसी मूल्य" प्राप्त कर सकते हैं, यदि आप डेटाबेस या नेटवर्किंग कॉल लागू करते हैं तो बहुत उपयोगी है, जहां बहुत से त्रुटि संदेशों की आवश्यकता हो सकती है, लेकिन केवल एक त्रुटि होने पर ही।

मैंने इस समाधान में सी ++ प्रश्न में भी प्रवेश किया है कि ओपी का जिक्र है।


कक्षाएं, संरचनाएं, संग्रह और Arrays में कई मान हो सकते हैं। आउटपुट और संदर्भ पैरामीटर को फ़ंक्शन में भी सेट किया जा सकता है। ट्यूपल्स के माध्यम से गतिशील और कार्यात्मक भाषाओं में एकाधिक मानों को वापस करना संभव है, लेकिन सी # में नहीं।


पिछला पोस्टर सही है। आप सी # विधि से कई मान वापस नहीं कर सकते हैं। हालांकि, आपके पास कुछ विकल्प हैं:

  • एक ऐसी संरचना लौटाएं जिसमें एकाधिक सदस्य हों
  • एक वर्ग का एक उदाहरण लौटें
  • आउटपुट पैरामीटर का उपयोग करें ( आउट या रेफरी कीवर्ड का उपयोग करना)
  • आउटपुट के रूप में एक शब्दकोश या कुंजी-मूल्य जोड़ी का प्रयोग करें

पेशेवरों और विपक्ष को अक्सर पता लगाना मुश्किल होता है। यदि आप एक संरचना वापस करते हैं, तो सुनिश्चित करें कि यह छोटा है क्योंकि structs मूल्य प्रकार हैं और ढेर पर पारित किया गया है। यदि आप किसी वर्ग के उदाहरण को वापस लौटते हैं, तो यहां कुछ डिज़ाइन पैटर्न हैं जो आप समस्याओं का सामना करने से बचने के लिए उपयोग करना चाहते हैं - कक्षाओं के सदस्यों को संशोधित किया जा सकता है क्योंकि सी # संदर्भ द्वारा ऑब्जेक्ट पास करता है (आपके पास वीबी में आपके जैसे बीवल नहीं हैं )।

अंत में आप आउटपुट पैरामीटर का उपयोग कर सकते हैं लेकिन मैं इसका उपयोग परिदृश्यों तक सीमित कर दूंगा जब आपके पास केवल दो जोड़े (जैसे 3 या कम) पैरामीटर हों - अन्यथा चीजें बदसूरत और बनाए रखने के लिए कठिन होती हैं। इसके अलावा, आउटपुट पैरामीटर का उपयोग चपलता के लिए अवरोधक हो सकता है क्योंकि जब भी आपको रिटर्न वैल्यू में कुछ जोड़ने की आवश्यकता होती है तो आपके विधि हस्ताक्षर को बदलना होगा जबकि एक स्ट्रक्चर या क्लास इंस्टेंस लौटाते हुए आप विधि हस्ताक्षर को संशोधित किए बिना सदस्यों को जोड़ सकते हैं।

एक वास्तुशिल्प दृष्टिकोण से मैं कुंजी-मूल्य जोड़े या शब्दकोशों का उपयोग करने के खिलाफ अनुशंसा करता हूं। मुझे लगता है कि कोडिंग की इस शैली को कोड में "गुप्त ज्ञान" की आवश्यकता है जो विधि का उपभोग करता है। यह समय से पहले पता होना चाहिए कि चाबियाँ क्या होने जा रही हैं और मूल्य क्या हैं और यदि आंतरिक कार्यान्वयन पर काम कर रहे डेवलपर शब्दकोश या केवीपी के तरीके को बदलता है, तो यह पूरे एप्लिकेशन में आसानी से विफलता कैस्केड बना सकता है।


मुख्य रूप से दो विधियां हैं। 1. आउट / रेफ पैरामीटर का उपयोग करें 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 कीवर्ड उन पैरामीटर का वर्णन करता है जिनके वास्तविक परिवर्तनीय स्थानों को बुलाए गए विधि के ढेर पर कॉपी किया जाता है, जहां वही स्थान पुनः लिखा जा सकता है। इसका मतलब है कि कॉलिंग विधि बदले गए पैरामीटर तक पहुंच जाएगी।

2) Tuple<T>

टुपल का उदाहरण:

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

नोट: टुपल का उपयोग फ्रेमवर्क 4.0 और उसके बाद से मान्य हैTuple प्रकार एक class । इसे स्मृति में प्रबंधित ढेर पर एक अलग स्थान पर आवंटित किया जाएगा। एक बार जब आप Tuple बनाते हैं, तो आप अपने fields के मानों को नहीं बदल सकते fields । यह Tuple को एक struct तरह बनाता है।


सी # 4 में, आप इसे आसानी से संभालने के लिए टुपल्स के लिए अंतर्निहित समर्थन का उपयोग करने में सक्षम होंगे।

इस बीच, दो विकल्प हैं।

सबसे पहले, आप अपने पैरामीटर को मान असाइन करने के लिए रेफरी या आउट पैरामीटर का उपयोग कर सकते हैं, जो कॉलिंग रूटीन पर वापस आते हैं।

ऐसा लगता है:

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

दूसरा, आप अपने रिटर्न वैल्यू को संरचना या कक्षा में लपेट सकते हैं, और उन्हें उस संरचना के सदस्यों के रूप में वापस भेज सकते हैं। KeyValuePair 2 के लिए अच्छी तरह से काम करता है - 2 से अधिक के लिए आपको कस्टम क्लास या स्ट्रक्चर की आवश्यकता होगी।


सी # के भविष्य संस्करण नामित tuples शामिल करने जा रहा है। डेमो के लिए इस चैनल 9 सत्र पर एक नज़र डालें 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

(वीडियो से अपूर्ण उदाहरण)


.NET 4.0 + के टुपल का प्रयोग करें:

उदाहरण के लिए:

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

दो मानों वाले Item1 में Item1 और Item1 गुण होते हैं।





return