2014-09-11 5 views
5

में अपरिवर्तनीय संरचना लिखने का सबसे छोटा तरीका अक्सर मुझे छोटे अपरिवर्तनीय डेटा संरचनाओं की आवश्यकता होती है। अन्य लोग शायद इन मामलों में टुपल्स का उपयोग करेंगे, लेकिन मैं वास्तव में नापसंद करता हूं कि टुपल्स अच्छी तरह से नहीं पढ़ते हैं और इतना अर्थ व्यक्त नहीं करते हैं। Value2int मुझे कुछ भी नहीं बताता है।सी #

एक उदाहरण दो गुणों के संयोजन के लिए एक लुकअप टेबल (शब्दकोश) बना रहा होगा, यानी Name और Rating

public struct Key 
{ 
    public string Name { get; private set; } 
    public int  Rating { get; private set; } 

    public LolCat(string name, int rating) : this() 
    { 
     Name = name; 
     Rating = rating; 
    } 
} 

// useage 
var key = new Key("MonorailCat", 5); 

मेरी राय में वहाँ अभी भी यहाँ में'वाक्यात्मक वसा' का एक बहुत है कि मैं चाहते हैं:

इन मामलों है कि मैं के बारे में पता करने के लिए एक अपरिवर्तनीय struct बनाने के लिए सबसे छोटा रास्ता यह है छुटकारा पाना। जब मैं सिर्फ फ़ील्ड का खुलासा करता हूं तो मैं इसे और अधिक पठनीय बना सकता हूं।

public struct Key 
{ 
    public string Name; 
    public int  Rating; 
} 

// useage 
var key = new Key { Name = "MonorailCat", Rating = 5 }; 

मुझे वास्तव में इसका वाक्यविन्यास पसंद है, क्योंकि वहां कोई भी वाक्य रचनात्मक वसा नहीं है। बड़ा नुकसान यह है कि यह अपरिवर्तनीय नहीं है, इसके सभी खतरों के साथ।

आदर्श मामले में मैं सिर्फ इस बात के लिए एक विशेष प्रकार की तरह, परिभाषा के वास्तविक न्यूनतम के साथ, करना चाहते हैं:

public immutable struct Key 
{ 
    string Name; 
    int  Rating; 
} 

// useage (needs compiler magic) 
var key = new Key(Name: "MonorailCat", Rating: 5); 

प्रश्न

वहाँ एक वास्तविक दुनिया समाधान है एक बहुत ही सरल अपरिवर्तनीय संरचना के लिए सिंटैक्टिक वसा की मात्रा को कम करने के लिए नीचे के उदाहरण के करीब कुछ?

+0

इस मामले में कक्षा का उपयोग क्यों नहीं करते? – Kao

+0

गुणों को 'readonly' फ़ील्ड के रूप में क्यों न उजागर करें? आप कम से कम '{get; निजी सेट;} '(और आपको अभी भी निर्माता की आवश्यकता होगी)। – casperOne

उत्तर

13

सी # 6 के रूप में, आप काफी कॉम्पैक्ट struct initializers लिख सकते हैं:

public struct Key 
{ 
    public string Name { get; } 
    public int Rating { get; } 

    public Key(string name, int rating) 
    { 
     this.Name = name; 
     this.Rating = rating; 
    } 
} 

... जो कम से कम काफी कम है। मैं दृढ़ता से IEquatable<Key> को लागू करने की सलाह देता हूं, आपको दिमाग में।

ध्यान दें कि आप एक struct साथ काम कर रहे हैं, तो आप अभी भी लिखने के लिए सक्षम हो जाएगा:

Key key = new Key(); 
Console.WriteLine(key.Rating); // 0 

... जो एक समस्या नहीं हो सकता है, लेकिन आम तौर पर जरूरत कम से कम पर विचार।

से पहले सी # 6, मैं वास्तव में भी लंबे समय तक अपने वर्तमान कोड से जाना चाहते हैं, ताकि केवल पढ़ने के लिए गुण के रूप में गुण लिखने के लिए:

public struct Key 
{ 
    private readonly string name; 
    private readonly int rating; 

    public string Name { get { return name; } } 
    public int Rating { get { return rating; } } 

    public Key(string name, int rating) 
    { 
     this.name = name; 
     this.rating = rating; 
    } 
} 

मुझे लगता है इस बनाता है यह और अधिक स्पष्ट रूप "होने का मतलब अपरिवर्तनीय "- यदि आपके पास एक लिखने योग्य संपत्ति है, भले ही सेटटर केवल निजी है, जो सही इंप्रेशन आईएमओ को व्यक्त नहीं करता है। (हालांकि यह ध्यान देने योग्य है कि structs में अपरिवर्तनीयता हमेशा कम बिट का एक झगड़ा है, बशर्ते आप सदस्यों में this असाइन कर सकें ...)

+0

हालांकि अभी भी गुणों का उपयोग क्यों कर रहे हैं, और X.L. जैसे रीडोनली फ़ील्ड को सीधे प्रकट नहीं कर रहे हैं। चींटियों उदाहरण? सिर्फ 'अर्थ' के लिए? –

+0

आह कभी बुरा मत मानो। उनके जवाब के तहत टिप्पणी पढ़ें। –

+0

@ डिर्कबॉयर: मैं बहुत ज्यादा * कभी * खेतों का पर्दाफाश नहीं करता हूं। यह मुझे सभी प्रकार के गलत लगता है :) –

2

AFAIK, कम से कम आप लिखते हैं केवल पढ़ने के लिए उपयोग कर रहा है, जो आपके struct गुण का उपयोग करने से शायद ही कम है कर सकते हैं:

public struct Key 
{ 
    public readonly string Name; 
    public readonly int  Rating; 

    public Key(string name, int rating){ 
     Name = name; 
     Rating = rating; 
    } 
} 

var key = new Key("MonorailCat", 5); 
+1

जबकि यह काम करता है, इसका मतलब यह है कि गुणों के बजाय * फ़ील्ड्स * को उजागर करना - जो कुछ मैं हमेशा से सावधान हूं। विशेष रूप से, इस से सी # 6 संपत्ति-आधारित संस्करण में बदलना एक तोड़ने वाला परिवर्तन है। –

+0

@ जोन्सस्केट मैं उस पर आपके साथ सहमत हूं, लेकिन मुझे किसी भी मामले की जानकारी नहीं है जहां पाठक क्षेत्रों को उजागर करने से समस्याएं हो सकती हैं (आपके द्वारा उल्लेख किए जाने वाले ब्रेकिंग परिवर्तन को छोड़कर)। क्या कोई मामला है जिसके बारे में मुझे अवगत होना चाहिए? –

+0

कार्यान्वयन के आधार पर, यूआई बाइंडिंग अक्सर फ़ील्ड के लिए सेट नहीं की जाती है - और भाषा में सभी प्रकार के स्थान होते हैं जहां गुणों और क्षेत्रों के बीच अंतर काफी सूक्ष्म होते हैं। यह * बुरा नहीं है * जब फ़ील्ड केवल पढ़ने के लिए होते हैं, लेकिन मैं अभी भी व्यक्तिगत रूप से गुणों का उपयोग करना पसंद करता हूं। मेरे दिमाग में, गुण एक प्रकार और उसके ग्राहकों के बीच एपीआई का हिस्सा हैं; खेतों में एक कार्यान्वयन विस्तार है। (उदाहरण के लिए नोडा समय में, मैंने हाल ही में सबकुछ बड़े पैमाने पर कार्यान्वित किया है - खेतों में पूरी तरह से बदलाव आया है, लेकिन गुण पहले जैसा ही हैं ...) –

1

सी # 7.2 में एक केवल पढ़ने के लिए struct है।

readonly public struct ReadonlyPoint3D 
{ 
    public ReadonlyPoint3D(double x, double y, double z) 
    { 
     this.X = x; 
     this.Y = y; 
     this.Z = z; 
    } 
    //setters would not compile 
    public double X { get; } 
    public double Y { get; } 
    public double Z { get; } 

    private static ReadonlyPoint3D origin = new ReadonlyPoint3D(); 
    public static ref readonly ReadonlyPoint3D Origin => ref origin; 
    public ReadonlyPoint3D Scale(double factor) 
    { 
     /* all fail compilation 
     X *= factor; 
     Y *= factor; 
     Z *= factor; 
     */ 
     return new ReadonlyPoint3D(X * factor, Y * factor, Z * factor); 
    } 
} 

कंपाइलर लागू करता है कि सभी सदस्य केवल पढ़े जाते हैं। यह रिसीवर की प्रतिलिपि के बजाय संदर्भ में 'इन' संदर्भ के रूप में पारित होता है जो आमतौर पर अधिक कुशल होता है।

Reference

+0

+1, हालांकि मैं कहूंगा "जो आमतौर पर अधिक कुशल होता है"। कुछ बार ऐसा होता है जब यह कम होता है। एक नियम के रूप में आप आमतौर पर खुश रह सकते हैं कि यह अधिकतर समय में अधिक कुशल होने जा रहा है, लेकिन यदि हॉटस्पॉट को अनुकूलित करने का प्रयास किया जाता है, जहां हॉटस्पॉट आंतरिक रीडोनली स्ट्रक्चर का उपयोग करता है तो प्रोफाइलिंग के लायक चीजों में से एक उस पाठ को बंद कर रहा है। –

+0

धन्यवाद। माना। बदला हुआ। – acarlon