2017-05-11 6 views
8

Fiddle hereसी # 7 मूल्य tuple/deconstruction asymmetry

एक समारोह (string a, string b) F() देखते हुए, आप टपल यह रिटर्न deconstruct कर सकते हैं:

var (a, b) = F(); 

(string c, string d) = F(); 

या आप बस इसे असाइन कर सकते हैं:

var (a, b) e = F(); 

(string a, string b) f = F(); 

var g = F(); // One of these things is not like the others. 

कक्षा deconstructors पहले मामले की तरह व्यवहार करते हैं। एक वर्ग CDeconstructor(out string a, out string b) साथ दिया गया है:

लेकिन संकलक Deconstructor का उपयोग नहीं होगा परोक्ष एक टपल करने के लिए इसे परिवर्तित करने के लिए:

// Cannot implicitly convert type 'C' to '(string a, string b)' 
var (a, b) l = c; 

जाहिर है आप यंत्रवत् Deconstructor के आधार पर एक अंतर्निहित रूपांतरण लिख सकते हैं :

public static implicit operator (string a, string b) (C c) 
{ 
    c.Deconstruct(out string a, out string b); 
    return (a, b); 
} 

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

यदि मैंने इस बारे में सोचा, तो सी # टीम ने इसके बारे में सोचा, और यदि उन्होंने निहित रूपांतरण के लिए "जादू" समर्थन नहीं जोड़ना चुना, तो उनके पास का एक अच्छा कारण था।

क्या कोई सकारात्मक कारण है कि अंतर्निहित रूपांतरण स्वचालित रूप से एक बुरा विचार क्यों होता?

या क्या यह उन सुविधाओं में से एक है जिन्हें लागत को उचित ठहराने के लिए पर्याप्त मूल्यवान नहीं माना जाता था?


यहाँ that fiddle से कोड है:

public class Program 
{ 
    public static void Main() 
    { 
     (string a, string b) = F(); 

     (string a, string b) ab = F(); 

     Console.WriteLine($"a: {a} b: {b} ab: {ab}"); 


     var c = new C(); 

     (string d, string e) = c; 

     // Cannot implicitly convert type 'C' to '(string a, string b)' 
     (string a, string b) f = c; 

     Console.WriteLine($"d: {d} e: {e} f: {f}"); 

     // Covariance 
     (object c, object d) g = F(); 
     // Implicit conversion 
     (double x, double y) t = G(); 
    } 

    public static (string a, string b) F() 
     => ("A", "B"); 

    public static (int x, int y) G() 
     => (0, 1); 
} 

public class C 
{ 
    public String A = "A"; 
    public String B = "B"; 

    public void Deconstruct(out String a, out String b) 
    { 
     a = A; 
     b = B; 
    } 
} 

सी # टीम हर कोई अधिक चालाक नहीं हो सकता है, लेकिन मैं पैसे सट्टेबाजी वे कम से कम के रूप में मुझे के रूप में स्मार्ट थे खो कभी नहीं किया है।

+0

जाहिर है, आप निहित निर्णायक नहीं चाहते हैं, वैसे ही आप आमतौर पर कक्षा से दूसरे में अंतर्निहित रूपांतरण नहीं चाहते हैं। इसके अलावा, यह एक ही स्रोत से tuple और deconstructed चर दोनों का उपयोग करने के लिए ज्यादा समझ में नहीं आता है। यह केवल कोड को समझने के लिए कठिन बना देगा। और एक भाषा डिजाइनर के रूप में, वैसे भी सख्त शुरू करने के लिए यह समझ में आता है और फिर अंततः इसके विपरीत से सामान्यीकृत होता है। उदाहरण के लिए, तथ्य यह है कि संदर्भ प्रकार डिफ़ॉल्ट रूप से शून्य हैं, सी # अब सबसे बड़ी डिजाइन गलती के रूप में माना जाता है ... – Phil1970

उत्तर

5

डीकोनस्ट्रक्ट्स को निहित कन्वर्टर्स की तरह कार्य करने की क्षमता सी # 7 जारी होने से पहले (मेरे द्वारा, इसलिए मैं यहां पक्षपातपूर्ण हूं) था। टीम की प्रतिक्रिया थी (जैसा कि मैंने इसे पढ़ा है) कि इसे सी # 7 रिलीज के बहुत करीब के लिए कहा गया था और इसे लागू करने में बहुत लंबा समय लगेगा, इसलिए विचार करने के लिए तैयार नहीं था। चूंकि यह अब एक तोड़ने वाला बदलाव होगा, यह ऐसा कुछ नहीं होगा जो कभी भी होगा।

कृपया इस मामले पर वास्तविक चर्चा के लिए "Allow Deconstruct and implicit operator to both support deconstruction and conversion to tuple types" roslyn repo मुद्दा देखें।

5

(string a, string b) ab एक एकल टपल प्रकार (string a, string b)ab नामित की चर की घोषणा की। यह आपको ab.a या ab.b लिखने देता है, लेकिन a या b नहीं लिखता है।

(string a, string b) f = c; इस टुपल प्रकार पर एक असंबंधित C प्रकार को परिवर्तित करने का प्रयास करता है। जब तक आप एक कलाकार नहीं लिखते, तब तक ऐसा होने का कोई तरीका नहीं है।

विशेष रूप से, जैसा कि नाम का तात्पर्य है, विनाश केवल आपको चर को असाइन करने देता है; यह आपको एक असंबंधित प्रकार में परिवर्तित करने की अनुमति नहीं देता है।

3

आप जो करने का प्रयास कर रहे हैं उसे प्राप्त करने का एक तरीका यहां है: (string a, string b) f = c; के बजाय, अपने कोड नमूने में, (string a, string b) f = (_, _) = c; का उपयोग करें।

आप अपने प्रकार से उपयोगकर्ता द्वारा परिभाषित रूपांतरण को आपके द्वारा आवश्यक टुपल प्रकार में भी लिख सकते हैं।

+0

मैं वास्तव में यहां चाल की प्रशंसा करता हूं! मैं कभी भी उत्पादन कोड में नहीं देखना चाहता, लेकिन यह साफ है :) –

संबंधित मुद्दे