मेरे C # कोड में .NET 4.0 टुपल्स का उपयोग करना एक खराब डिजाइन निर्णय है?


166

के अलावा के साथ टपल .net 4 में वर्ग, मैं अगर उन्हें अपने डिजाइन में उपयोग करते हुए एक बुरा विकल्प है या नहीं तय करने की कोशिश की है। जिस तरह से मैं इसे देखता हूं, एक ट्यूपल एक परिणाम वर्ग लिखने का एक शॉर्टकट हो सकता है (मुझे यकीन है कि अन्य उपयोग भी हैं)।

तो यह:

public class ResultType
{
    public string StringValue { get; set; }
    public int IntValue { get; set; }
}

public ResultType GetAClassedValue()
{
    //..Do Some Stuff
    ResultType result = new ResultType { StringValue = "A String", IntValue = 2 };
    return result;
}

इसके बराबर है:

public Tuple<string, int> GetATupledValue()
{
    //...Do Some stuff
    Tuple<string, int> result = new Tuple<string, int>("A String", 2);
    return result;
}

इसलिए इस संभावना को दरकिनार करते हुए कि मैं टुपल्स की बात को याद कर रहा हूं, क्या टुपल के साथ खराब डिजाइन का उदाहरण है ? मेरे लिए यह कम अव्यवस्था की तरह लगता है, लेकिन स्व-दस्तावेजीकरण और स्वच्छ के रूप में नहीं। मतलब कि प्रकार के साथ ResultType, यह बाद में बहुत स्पष्ट है कि कक्षा के प्रत्येक भाग का क्या अर्थ है, लेकिन आपके पास बनाए रखने के लिए अतिरिक्त कोड है। इसके साथ Tuple<string, int>आपको यह देखने और जानने की आवश्यकता होगी कि प्रत्येक क्या Itemदर्शाता है, लेकिन आप कम कोड लिखते हैं और बनाए रखते हैं।

इस विकल्प के साथ आपके पास जो भी अनुभव है वह बहुत सराहा जाएगा।


16
@Boltbait: क्योंकि ट्यूपल सेट सिद्धांत en.wikipedia.org/wiki/Tuple से है
मैथ्यू Whited

16
@BoltBait: एक "टपल" एक निर्धारित मान है, और जरूरी नहीं कि डेटाबेस में पंक्तियों के साथ कुछ भी हो।
FrustratedWithFormsDesigner

19
सी # में ट्यूपल भी अच्छे होते अगर कुछ अच्छा टपल अनपैकिंग एक्शन होता: :)
जस्टिन

4
@ जॉन सॉन्डर्स मेरा प्रश्न विशेष रूप से c # में डिज़ाइन निर्णयों के बारे में है। मैं किसी भी अन्य .net भाषाओं का उपयोग नहीं करता हूं, इसलिए मैं इस बात से अनिश्चित हूं कि ट्यूपल्स उन्हें कैसे प्रभावित करते हैं। इसलिए मैंने इसे सी # चिह्नित किया। यह मुझे उचित लगा लेकिन .net के लिए बदलाव ठीक है, मुझे लगता है।
जेसन वेब

13
@ जॉन सौन्डर्स: मुझे पूरा यकीन है कि वह एक अनुप्रयोग में टुपल्स का उपयोग करने या न करने से संबंधित डिज़ाइन निर्णयों के बारे में पूछ रहे हैं जो विशुद्ध रूप से C # में लिखे गए हैं। मुझे विश्वास नहीं होता कि वह उन डिजाइन निर्णयों के बारे में पूछ रहा है जो C # भाषा बनाने में गए थे।
ब्रेट विडमियर

जवाबों:


163

ट्यूपल्स महान हैं यदि आप उन्हें बनाने और उनका उपयोग करने को नियंत्रित करते हैं - आप संदर्भ को बनाए रख सकते हैं, जो उन्हें समझने के लिए आवश्यक है।

एक सार्वजनिक एपीआई पर, हालांकि, वे कम प्रभावी हैं। उपभोक्ता (आप नहीं) को या तो अनुमान लगाना पड़ता है या प्रलेखन देखना पड़ता है, विशेष रूप से जैसी चीजों के लिए Tuple<int, int>

मैं उनका उपयोग निजी / आंतरिक सदस्यों के लिए करूंगा, लेकिन सार्वजनिक / संरक्षित सदस्यों के लिए परिणाम कक्षाओं का उपयोग करूंगा।

इस जवाब में कुछ जानकारी भी है।


19
सार्वजनिक / निजी के बीच का अंतर वास्तव में महत्वपूर्ण है, इसे लाने के लिए धन्यवाद। अपने सार्वजनिक एपीआई में ट्यूपल्स को लौटाना वास्तव में एक बुरा विचार है, लेकिन आंतरिक रूप से जहां चीजें कसकर युग्मित हो सकती हैं (लेकिन यह ठीक है ) यह ठीक है।
क्लिंटन पियर्स

36
कसकर युग्मित, या कसकर उलझा हुआ? ;)
संपर्कमात्रा

क्या उपयुक्त प्रलेखन यहाँ उपयोगी नहीं हो सकता है? उदाहरण के लिए, स्काला की StringOps(मूल रूप से जावा के लिए "विस्तार विधियों का एक वर्ग" String) में एक विधि है parition(Char => Boolean): (String, String)(विधेय में ले जाती है, 2 तारों का टपल देता है)। यह स्पष्ट है कि आउटपुट क्या है (स्पष्ट रूप से एक ऐसा चरित्र होने जा रहा है जिसके लिए विधेय सत्य था और दूसरा जिसके लिए यह गलत था, लेकिन यह स्पष्ट नहीं है कि कौन सा है)। यह प्रलेखन है जो इसे साफ करता है (और पैटर्न मिलान का उपयोग यह स्पष्ट करने के लिए किया जा सकता है कि यह कौन सा है)।
कैट

@ माइक: यह सही और आसान गलत पाने के लिए कठिन बनाता है, एक एपीआई की पहचान जो किसी के लिए दर्द का कारण बन जाएगा :-)
ब्रायन वत्स

79

जिस तरह से मैं इसे देखता हूं, एक ट्यूपल एक परिणाम वर्ग लिखने का एक शॉर्टकट है (मुझे यकीन है कि अन्य उपयोग भी हैं)।

वास्तव में अन्य मूल्यवान उपयोग हैं Tuple<> - उनमें से अधिकांश में एक विशेष प्रकार के समूह के शब्दार्थ को अलग करना शामिल है जो एक समान संरचना साझा करते हैं, और उन्हें केवल मानों के सेट के रूप में व्यवहार करते हैं। सभी मामलों में, टुपल्स का एक लाभ यह है कि वे आपके नाम स्थान को केवल डेटा वर्ग के साथ अव्यवस्थित करने से बचते हैं जो गुणों को उजागर करते हैं, लेकिन विधियां हैं।

यहाँ के लिए एक उचित उपयोग का एक उदाहरण है Tuple<>:

var opponents = new Tuple<Player,Player>( playerBob, playerSam );

उपरोक्त उदाहरण में हम विरोधियों की एक जोड़ी का प्रतिनिधित्व करना चाहते हैं, एक टपल एक नया वर्ग बनाने के बिना इन उदाहरणों को बाँधने का एक सुविधाजनक तरीका है। यहाँ एक और उदाहरण है:

var pokerHand = Tuple.Create( card1, card2, card3, card4, card5 );

एक पोकर हाथ को कार्ड के एक सेट के रूप में माना जा सकता है - और टपल (हो सकता है) उस अवधारणा को व्यक्त करने का एक उचित तरीका है।

इस संभावना को दरकिनार करते हुए कि मैं टुपल्स की बात को याद कर रहा हूं, क्या टुपल के साथ एक खराब डिजाइन का उदाहरण है?

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

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

अंगूठे का मेरा नियम है: यदि आप इसे अपने सार्वजनिक इंटरफ़ेस से वापस कर देंगे - इसे एक नामांकित प्रकार बनाएं

Tuples का उपयोग करने के लिए अंगूठे का मेरा अन्य नियम है: नाम विधि तर्क और प्रकार के स्थानीय चर Tuple<>स्पष्ट रूप से संभव के रूप में - नाम को tuple के तत्वों के बीच संबंधों के अर्थ का प्रतिनिधित्व करते हैं। मेरे var opponents = ...उदाहरण के बारे में सोचो ।

यहां एक वास्तविक दुनिया का एक उदाहरण है जहां मैंने केवल अपनी विधानसभा के भीतर उपयोग के लिएTuple<> डेटा-केवल प्रकार घोषित करने से बचने के लिए उपयोग किया है । स्थिति में यह तथ्य शामिल है कि जब सामान्य प्रकारों वाले अनाम शब्दकोशों का उपयोग किया जाता है TryGetValue(), तो शब्दकोश में आइटम खोजने के लिए विधि का उपयोग करना मुश्किल हो जाता है क्योंकि विधि को एक outपैरामीटर की आवश्यकता होती है जिसे नाम नहीं दिया जा सकता है:

public static class DictionaryExt 
{
    // helper method that allows compiler to provide type inference
    // when attempting to locate optionally existent items in a dictionary
    public static Tuple<TValue,bool> Find<TKey,TValue>( 
        this IDictionary<TKey,TValue> dict, TKey keyToFind ) 
    {
        TValue foundValue = default(TValue);
        bool wasFound = dict.TryGetValue( keyToFind, out foundValue );
        return Tuple.Create( foundValue, wasFound );
    }
}

public class Program
{
    public static void Main()
    {
        var people = new[] { new { LastName = "Smith", FirstName = "Joe" },
                             new { LastName = "Sanders", FirstName = "Bob" } };

        var peopleDict = people.ToDictionary( d => d.LastName );

        // ??? foundItem <= what type would you put here?
        // peopleDict.TryGetValue( "Smith", out ??? );

        // so instead, we use our Find() extension:
        var result = peopleDict.Find( "Smith" );
        if( result.First )
        {
            Console.WriteLine( result.Second );
        }
    }
}

PS वहाँ शब्दकोशों में गुमनाम प्रकार से उत्पन्न होने वाले मुद्दों के आसपास का एक और (सरल) तरीका है, और यह है कि varकंपाइलर का उपयोग करके 'कंपाइलर' को आपके लिए टाइप करें। यहाँ वह संस्करण है:

var foundItem = peopleDict.FirstOrDefault().Value;
if( peopleDict.TryGetValue( "Smith", out foundItem ) )
{
   // use foundItem...
}

5
@stakx: हां, मैं सहमत हूं। लेकिन ध्यान रखें - उदाहरण काफी हद तक मामलों को चित्रित करने के लिए अभिप्रेत है जब एक का उपयोग समझ में आ Tuple<> सकता है। हमेशा विकल्प होते हैं ...
LBushkin

1
मुझे लगता है कि TryGetValue या TryParse के रूप में एक Tuple के साथ मापदंडों को प्रतिस्थापित करना, उन कुछ मामलों में से एक है जहां सार्वजनिक API को Tuple वापस करने का कोई मतलब हो सकता है। वास्तव में, कम से कम एक .NET भाषा स्वचालित रूप से आपके लिए यह एपीआई परिवर्तन बनाती है।
जोएल मुलर

1
@stakx: ट्यूपल भी अपरिवर्तनीय हैं, जबकि सरणियाँ नहीं हैं।
रॉबर्ट पॉलसन

2
मुझे समझ में आया कि टुपल्स केवल अपरिवर्तनीय पोकर प्लेयर ऑब्जेक्ट्स के रूप में उपयोगी हैं।
गेन्नेडी वनिन Геннадий Ванин

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

18

टुपल्स उपयोगी हो सकते हैं ... लेकिन वे बाद में दर्द भी हो सकते हैं। यदि आपके पास एक तरीका है जो आपको लौटाता है Tuple<int,string,string,int>तो आप कैसे जानते हैं कि वे मूल्य बाद में क्या हैं। वे थे ID, FirstName, LastName, Ageया वे थे UnitNumber, Street, City, ZipCode


9

सी # प्रोग्रामर के नजरिए से टुपल्स सीएलआर के अतिरिक्त बहुत ही कम होते हैं। यदि आपके पास उन वस्तुओं का संग्रह है जो लंबाई में भिन्न हैं, तो आपको उन्हें संकलन समय पर अद्वितीय स्थिर नाम रखने की आवश्यकता नहीं है।

लेकिन अगर आपके पास निरंतर लंबाई का संग्रह है, तो इसका मतलब यह है कि संग्रह में निश्चित स्थानों के प्रत्येक का एक विशिष्ट पूर्व-परिभाषित अर्थ है। और यह है हमेशा उन्हें बेहतर नहीं बल्कि के महत्व को याद करने के लिए की तुलना में, उस मामले में उचित स्थिर नाम देने के लिए Item1, Item2आदि

C # में अनाम कक्षाएं पहले से ही ट्यूपल्स के सबसे आम निजी उपयोग के लिए एक शानदार समाधान प्रदान करती हैं, और वे वस्तुओं को सार्थक नाम देते हैं, इसलिए वे वास्तव में उस अर्थ में श्रेष्ठ हैं। एकमात्र समस्या यह है कि वे नामित विधियों से लीक नहीं हो सकते हैं। मैं यह देखना चाहूंगा कि सी # में ट्यूल के लिए विशिष्ट समर्थन की तुलना में उठाया गया प्रतिबंध (शायद केवल निजी तरीकों के लिए) है:

private var GetDesserts()
{
    return _icecreams.Select(
        i => new { icecream = i, topping = new Topping(i) }
    );
}

public void Eat()
{
    foreach (var dessert in GetDesserts())
    {
        dessert.icecream.AddTopping(dessert.topping);
        dessert.Eat();
    }
}

एक सामान्य विशेषता के रूप में, जो मैं देखना चाहूंगा वह कुछ विशेष प्रकार के अनाम प्रकारों के लिए एक मानक को परिभाषित करने के लिए .net है, जैसे कि struct var SimpleStruct {int x, int y;}एक नाम के साथ एक संरचना को परिभाषित करेगा जो सरल संरचना से जुड़े एक गाइड के साथ शुरू होता है और कुछ {System.Int16 x}{System.Int16 y}जोड़ा है; उस GUID से शुरू होने वाले किसी भी नाम को केवल उन तत्वों और विशेष रूप से निर्दिष्ट सामग्रियों वाली संरचना का प्रतिनिधित्व करना आवश्यक होगा; यदि एक ही नाम की कई परिभाषाएँ दायरे में हैं और वे मेल खाती हैं, तो सभी को एक ही प्रकार माना जाएगा।
सुपरकैट

ऐसी चीज कुछ प्रकारों के लिए सहायक होगी, जिसमें उत्परिवर्तनीय और अपरिवर्तनीय वर्ग- और संरचना- tuples के साथ-साथ उन स्थितियों में उपयोग के लिए इंटरफेस और डेलिगेट्स शामिल हैं जहां मिलान संरचना को शब्दार्थ मिलान करने के लिए समझा जाना चाहिए। हालांकि निश्चित रूप से कारण हैं कि दो प्रतिनिधि प्रकारों के लिए उपयोगी हो सकता है जिनके समान पैरामीटर हैं जिन्हें विनिमेय नहीं माना जा सकता है, यह भी उपयोगी होगा यदि कोई निर्दिष्ट कर सकता है कि एक प्रतिनिधि एक प्रतिनिधि चाहता है जो मापदंडों के कुछ संयोजन लेता है लेकिन उस से परे नहीं है 'यह ध्यान रखें कि यह किस प्रकार का प्रतिनिधि है।
सुपरकाट

यह दुर्भाग्यपूर्ण है कि अगर दो अलग-अलग लोग फ़ंक्शंस लिखना चाहते हैं, जो इनपुट डेलिगेट्स के रूप में लेते हैं ref, जिन्हें एकल पैरामीटर की आवश्यकता होती है , तो एक ही प्रतिनिधि के लिए एक ही तरीका संभव होगा जो दोनों कार्यों को पारित कर सकता है यदि एक व्यक्ति उत्पादन करता है और एक संकलन करता है प्रतिनिधि प्रकार और खिलाफ निर्माण के लिए दूसरे को देता है। ऐसा कोई तरीका नहीं है कि दोनों लोग यह संकेत दे सकें कि दो प्रकारों को समानार्थी माना जाना चाहिए।
सुपरकैट

क्या आपके पास इसके बजाय और भी ठोस उदाहरण हैं जहां आप अनाम कक्षाओं का उपयोग करेंगे Tuple? मैंने अपने कोडबेस में केवल 50 स्थानों के माध्यम से स्किम्ड किया है जहां मैं ट्यूपल्स का उपयोग कर रहा हूं, और सभी या तो रिटर्न मान हैं (आमतौर पर yield return) या संग्रह के तत्व हैं जो कहीं और उपयोग किए जाते हैं, इसलिए अनाम कक्षाओं के लिए नहीं जाते हैं।

2
@JonofAllTrades - राय शायद उस पर अलग-अलग हैं, लेकिन मैं सार्वजनिक तरीकों को डिजाइन करने की कोशिश करता हूं जैसे कि वे किसी और के द्वारा उपयोग किए जा रहे थे, भले ही वह कोई भी हो, इसलिए मैं खुद को अच्छी ग्राहक सेवा दे रहा हूं! आप किसी फ़ंक्शन को लिखने से अधिक बार कॉल करते हैं। :)
डैनियल इयरविकर

8

कीवर्ड के समान var, यह एक सुविधा के रूप में अभिप्रेत है - लेकिन उतना ही आसानी से दुरुपयोग किया जाता है।

मेरी सबसे विनम्र राय में, Tupleएक वापसी वर्ग के रूप में उजागर न करें । यदि किसी सेवा या घटक के डेटा संरचना को इसकी आवश्यकता है, तो इसे निजी रूप से उपयोग करें, लेकिन सार्वजनिक विधियों से अच्छी तरह से गठित अच्छी तरह से ज्ञात कक्षाएं लौटाएं।

// one possible use of tuple within a private context. would never
// return an opaque non-descript instance as a result, but useful
// when scope is known [ie private] and implementation intimacy is
// expected
public class WorkflowHost
{
    // a map of uri's to a workflow service definition 
    // and workflow service instance. By convention, first
    // element of tuple is definition, second element is
    // instance
    private Dictionary<Uri, Tuple<WorkflowService, WorkflowServiceHost>> _map = 
        new Dictionary<Uri, Tuple<WorkflowService, WorkflowServiceHost>> ();
}

2
मुख्यधारा "रेड" भाषाओं (जावा सबसे अच्छा उदाहरण है) ने हमेशा सुरक्षा को चुना है और अपने आप को पैर प्रकार के परिदृश्यों में शूटिंग से बचना है। मुझे खुशी है कि Microsoft C # के साथ कुछ मौके ले रहा है और भाषा को कुछ अच्छी शक्ति दे रहा है, भले ही इसका दुरुपयोग हो।
मैट ग्रीर

4
वॉर कीवर्ड का दुरुपयोग संभव नहीं है। शायद आप गतिशील थे?
Mar में क्रिस मैरिसिक

@ क्रिस मैरिसिक, बस स्पष्ट करने के लिए मेरा मतलब एक ही परिदृश्य में नहीं था - आप बिल्कुल सही हैं, varवापस पारित नहीं किया जा सकता है या इसके घोषित दायरे के बाहर मौजूद नहीं हो सकता है। हालांकि, यह अभी भी में इसका उपयोग करना संभव है अतिरिक्त अपने उद्देश्य उद्देश्य की और "दुरुपयोग" हो
जॉनी जी

5
मैं अभी भी उस संस्करण पर टिका हूं, जिसका दुरुपयोग नहीं किया जा सकता है। यह केवल एक छोटी चर परिभाषा बनाने के लिए एक खोजशब्द है। आपका तर्क शायद अनाम प्रकारों के बारे में है, लेकिन यहां तक ​​कि उन लोगों के साथ वास्तव में दुर्व्यवहार नहीं किया जा सकता है क्योंकि वे अभी भी सामान्य रूप से जुड़े हुए हैं प्रकार गतिशील अब एक अलग कहानी है।
क्रिस मैरिसिक

4
var का दुरुपयोग इस अर्थ में किया जा सकता है कि यदि इसका अत्यधिक उपयोग किया जाता है तो यह कभी-कभी कोड पढ़ने वाले व्यक्ति के लिए समस्याएँ पैदा कर सकता है। खासकर अगर आप विजुअल स्टूडियो में नहीं हैं और उसमें कमी है।
मैट ग्रीर

5

कक्षा का उपयोग करना ResultTypeस्पष्ट है। आप कक्षा में फ़ील्ड को सार्थक नाम दे सकते हैं (जबकि एक टपल के साथ उन्हें बुलाया जाएगा Item1और Item2)। यह और भी महत्वपूर्ण है अगर दो क्षेत्रों के प्रकार समान हैं: नाम स्पष्ट रूप से उनके बीच अंतर करता है।


एक छोटा अतिरिक्त लाभ: आप सुरक्षित रूप से एक वर्ग के लिए मापदंडों को फिर से व्यवस्थित कर सकते हैं। टूप्ले के लिए ऐसा करने से कोड टूट जाएगा, और यदि फ़ील्ड में समान प्रकार हैं तो यह संकलन समय पर पता लगाने योग्य नहीं हो सकता है।

मैं मानता हूं, टुपल्स का उपयोग तब किया जाता है जब एक डेवलपर को सार्थक संपत्ति नामों को समूहीकृत करने के लिए सार्थक वर्ग नाम सोचने की ऊर्जा की कमी होती है। प्रोग्रामिंग संचार के बारे में है। ट्यूपल्स संचार के लिए एक एंटीपैटर्न हैं। मैंने पसंद किया होगा कि Microsoft डेवलपर्स को अच्छा डिज़ाइन निर्णय लेने के लिए मजबूर करने के लिए इसे भाषा से बाहर छोड़ दे।
माइक गोल्ड

5

सजावट-अघोषित पैटर्न में ट्यूपल्स का उपयोग करने के बारे में कैसे? (पर्ल लोगों के लिए श्वार्टज़ियन ट्रांसफ़ॉर्म)। यहाँ एक निश्चित उदाहरण है, सुनिश्चित करने के लिए, लेकिन इस तरह की चीज़ को संभालने के लिए टुपल्स एक अच्छा तरीका है:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] files = Directory.GetFiles("C:\\Windows")
                    .Select(x => new Tuple<string, string>(x, FirstLine(x)))
                    .OrderBy(x => x.Item2)
                    .Select(x => x.Item1).ToArray();
        }
        static string FirstLine(string path)
        {
            using (TextReader tr = new StreamReader(
                        File.Open(path, FileMode.Open)))
            {
                return tr.ReadLine();
            }
        }
    }
}

अब, मैं दो तत्वों के एक ऑब्जेक्ट [] का उपयोग कर सकता था या इस विशिष्ट उदाहरण में दो तत्वों का एक स्ट्रिंग []। बिंदु यह है कि मैं टुपल में दूसरे तत्व के रूप में कुछ भी इस्तेमाल कर सकता था जो आंतरिक रूप से उपयोग किया जाता है और पढ़ने में बहुत आसान है।


3
आप कंस्ट्रक्टर के बजाय Tuple.Create का उपयोग कर सकते हैं। यह छोटा है।
कुगेल

एक अनाम प्रकार बहुत अधिक पठनीय होगा; के रूप में 'x' के बजाय वास्तविक चर नामों का उपयोग करेगा
डेव कूसिन्यू

यह अब होगा । यह एक एसओ समस्या है, साल और साल पहले पोस्ट किए गए उत्तर कभी भी नई तकनीक के लिए साफ या अपडेट नहीं किए जाते हैं।
क्लिंटन पियर्स

4

IMO ये "टुपल्स" मूल रूप से अनाम सदस्यों के साथ सभी सार्वजनिक पहुँच अनाम structप्रकार हैं

केवल जगह मैं का प्रयोग करेंगे टपल है जब आप एक बहुत ही सीमित दायरे में, जल्दी से एक साथ कुछ डेटा बूँद की जरूरत है। डेटा का शब्दार्थ स्पष्ट होना चाहिए , इसलिए कोड को पढ़ना मुश्किल नहीं है। एक टपल (का उपयोग कर तो int, intके लिए) (पंक्ति, स्तंभ) उचित लगता है। लेकिन मैं structनामांकित सदस्यों के साथ एक लाभ खोजने के लिए कठोर हूं (इसलिए कोई गलती नहीं की जाती है और पंक्ति / स्तंभ गलती से नहीं बदले हैं)

यदि आप कॉलर को डेटा वापस भेज रहे हैं, या किसी कॉलर से डेटा स्वीकार कर रहे हैं, तो आपको वास्तव में structनामित सदस्यों के साथ उपयोग करना चाहिए ।

एक सरल उदाहरण लें:

struct Color{ float r,g,b,a ; }
public void setColor( Color color )
{
}

टपल संस्करण

public void setColor( Tuple<float,float,float,float> color )
{
  // why?
}

मुझे नामांकित सदस्यों के साथ संरचना के स्थान पर टपल का उपयोग करने का कोई लाभ नहीं दिखता है। अनाम सदस्यों का उपयोग आपके कोड की पठनीयता और समझ के लिए एक कदम पीछे है।

टुपल ने मुझे structवास्तविक नामांकित सदस्यों के साथ बनाने से बचने के लिए एक आलसी तरीके से हमला किया । अति प्रयोग, जहां आप वास्तव में आपको महसूस करते हैं / या आपके कोड का सामना करने वाले किसी अन्य व्यक्ति को नामांकित सदस्यों की आवश्यकता होगी, यदि मैंने कभी देखा है तो यह एक बुरा बात है।


3

मुझे जज मत करो, मैं एक विशेषज्ञ नहीं हूं, लेकिन अब सी # 7.x में नए ट्यूपल के साथ, आप कुछ इस तरह से लौट सकते हैं:

return (string Name1, int Name2)

कम से कम अब आप इसे नाम दे सकते हैं और डेवलपर्स कुछ जानकारी देख सकते हैं।


2

यह निर्भर करता है, बिल्कुल! जैसा कि आपने कहा, एक ट्यूपल आपको स्थानीय उपभोग के लिए कुछ वस्तुओं को एक साथ समूहित करने के लिए कोड और समय बचा सकता है। यदि आप एक ठोस वर्ग के आसपास से गुजरते हैं तो आप उनसे अधिक सामान्य प्रसंस्करण एल्गोरिदम बनाने के लिए भी उपयोग कर सकते हैं। मैं याद नहीं कर सकता कि मैंने कितनी बार कामना की है कि मेरे पास KeyValuePair या DataRow से परे कुछ है जो जल्दी से एक विधि से दूसरे में कुछ तारीख पारित कर सकता है।

दूसरी ओर, इसे पूरा करना और ट्यूपल्स के आसपास से गुजरना काफी संभव है जहां आप केवल अनुमान लगा सकते हैं कि उनमें क्या है। यदि आप कक्षाओं में टपल का उपयोग करने जा रहे हैं, तो शायद एक ठोस वर्ग बनाना बेहतर होगा।

निश्चित रूप से मॉडरेशन में उपयोग किया जाता है, ट्यूपल्स अधिक संक्षिप्त और पठनीय कोड को जन्म दे सकते हैं। आप T ++ को अन्य भाषाओं में कैसे उपयोग किया जाता है, इसके उदाहरणों के लिए आप C ++, STL और बूस्ट को देख सकते हैं, लेकिन अंत में, हम सभी को यह पता लगाने के लिए प्रयोग करना होगा कि वे .NET वातावरण में सबसे अच्छे से कैसे फिट होते हैं।


1

Tuples .NET 4 में एक बेकार फ्रेमवर्क फ़ीचर है। मुझे लगता है कि C # 4.0 के साथ एक शानदार मौका छूट गया था। मुझे नामित सदस्यों के साथ टुपल्स करना पसंद था, इसलिए आप वैल्यू 1 , वैल्यू 2 , आदि के बजाय नाम से टपल के विभिन्न क्षेत्रों तक पहुंच सकते हैं ...

इसके लिए एक भाषा (वाक्यविन्यास) परिवर्तन की आवश्यकता होती, लेकिन यह बहुत उपयोगी होती।


टुपल्स एक "भाषा सुविधा" कैसे हैं? यह एक वर्ग सभी .net भाषाओं के लिए उपलब्ध है ना?
जेसन वेब

11
सी # के लिए अपेक्षाकृत बेकार, शायद। लेकिन System.Tuple को C # की वजह से फ्रेमवर्क में नहीं जोड़ा गया। एफ # और अन्य भाषाओं के बीच अंतर को कम करने के लिए इसे जोड़ा गया था।
जोएल म्यूलर

@ जेसन: मैंने यह नहीं कहा था कि यह एक भाषा सुविधा थी (मैंने यह गलत किया, लेकिन मैंने यह टिप्पणी करने से पहले आपको इसे ठीक कर दिया)।
फिलिप लेबेर्ट

2
@ जेसन - ट्यूपल्स के प्रत्यक्ष समर्थन वाली भाषाओं में ट्यूपल्स को उनके घटक मूल्यों में डिकंस्ट्रक्ट करने के लिए निहित समर्थन है। उन भाषाओं में लिखे गए कोड आमतौर पर कभी भी, आइटम 1, आइटम 2 के गुणों तक पहुँचते हैं। let success, value = MethodThatReturnsATuple()
जोएल म्यूलर

@Joel: इस प्रश्न को C # के रूप में चिह्नित किया गया है, इसलिए यह किसी तरह C # के बारे में है। मुझे अभी भी लगता है कि वे इसे भाषा में प्रथम श्रेणी के फीचर में बदल सकते थे।
फिलिप लेबेर्ट

1

मैं व्यक्तिगत रूप से एक Tuple का उपयोग रिटर्न प्रकार के रूप में कभी नहीं करूंगा क्योंकि मूल्यों का प्रतिनिधित्व करने वाले का कोई संकेत नहीं है। टुपल्स के कुछ मूल्यवान उपयोग हैं क्योंकि वस्तुओं के विपरीत वे मूल्य प्रकार हैं और इस प्रकार समानता को समझते हैं। इसके कारण मैं उन्हें शब्दकोश कुंजियों के रूप में उपयोग करूँगा, अगर मुझे मल्टीपार्ट कुंजी की आवश्यकता है या ग्रुपबी क्लॉज़ की कुंजी के रूप में अगर मुझे कई चर द्वारा समूह बनाना है और नेस्टेड ग्रुपिंग नहीं चाहिए (जो कभी नेस्टेड ग्रुपिंग चाहते हैं?)। अत्यधिक वाचालता के साथ समस्या को दूर करने के लिए आप उन्हें सहायक विधि से बना सकते हैं। ध्यान रखें कि यदि आप अक्सर सदस्यों (आइटम 1, आइटम 2, आदि के माध्यम से) तक पहुंच रहे हैं, तो आपको संभवतः एक अलग निर्माण का उपयोग करना चाहिए जैसे कि एक संरचना या एक अनाम वर्ग।


0

मैंने कई अलग-अलग परिदृश्यों में टुपल्स, दोनों Tupleऔर नए का उपयोग किया है, ValueTupleऔर निम्नलिखित निष्कर्ष पर पहुंचे: उपयोग न करें

हर बार, मुझे निम्नलिखित मुद्दों का सामना करना पड़ा:

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

मेरी राय है कि ट्यूपल एक बाधा हैं, न कि एक सुविधा, C # की।

मैं कुछ इसी तरह है, लेकिन बहुत कम कठोर, की आलोचना Func<>और Action<>। वे कई स्थितियों में उपयोगी हैं, विशेष रूप से सरल Actionऔर Func<type>भिन्न, लेकिन इससे परे कुछ भी, मैंने पाया है कि एक प्रतिनिधि प्रकार का निर्माण अधिक सुरुचिपूर्ण, पठनीय, बनाए रखने योग्य है, और आपको अधिक सुविधाएँ प्रदान करता है, जैसे ref/ outपैरामीटर।


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

मैं उन बिंदुओं से सहमत हूं। जब मैं निर्माता और उपभोक्ता को नियंत्रित करता हूं, तो मैं केवल टुपल्स का उपयोग करने की कोशिश करता हूं, और यदि वे "बहुत दूर" नहीं हैं। एक ही विधि में अर्थ, उत्पादक और उपभोक्ता = 'करीब', जबकि विभिन्न विधानसभाओं में निर्माता और उपभोक्ता = 'प्रकाश वर्ष दूर'। तो, अगर मैं एक विधि की शुरुआत में ट्यूपल्स बनाता हूं, और अंत में उनका उपयोग करता हूं? ज़रूर, मैं उसके साथ ठीक हूँ। मैं भी शर्तों और इस तरह के दस्तावेज। लेकिन हाँ, मैं मानता हूँ कि आम तौर पर वे सही विकल्प नहीं हैं।
माइक क्रिस्टियनन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.