स्थैतिक सूचकांक?


119

C # में स्टैटिक इंडेक्सर्स क्यों अस्वीकृत हैं? मुझे कोई कारण नहीं है कि उन्हें अनुमति क्यों नहीं दी जानी चाहिए और इसके अलावा वे बहुत उपयोगी हो सकते हैं।

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

public static class ConfigurationManager 
{
        public object this[string name]
        {
            get => ConfigurationManager.getProperty(name);
            set => ConfigurationManager.editProperty(name, value);
        }

        /// <summary>
        /// This will write the value to the property. Will overwrite if the property is already there
        /// </summary>
        /// <param name="name">Name of the property</param>
        /// <param name="value">Value to be wrote (calls ToString)</param>
        public static void editProperty(string name, object value) 
        {
            var ds = new DataSet();
            var configFile = new FileStream("./config.xml", FileMode.OpenOrCreate);
            ds.ReadXml(configFile);

            if (ds.Tables["config"] == null)
                ds.Tables.Add("config");

            var config = ds.Tables["config"];

            if (config.Rows[0] == null) 
                config.Rows.Add(config.NewRow());

            if (config.Columns[name] == null) 
                config.Columns.Add(name);

            config.Rows[0][name] = value.ToString();

            ds.WriteXml(configFile);
            configFile.Close();
        }

        public static void addProperty(string name, object value) =>
            ConfigurationManager.editProperty(name, value);

        public static object getProperty(string name) 
        {
            var ds = new DataSet();
            var configFile = new FileStream("./config.xml", FileMode.OpenOrCreate);
            ds.ReadXml(configFile);
            configFile.Close();

            if (ds.Tables["config"] == null) return null;

            var config = ds.Tables["config"];

            if (config.Rows[0] == null) return null;
            if (config.Columns[name] == null) return null;

            return config.Rows[0][name];
        }
    }

उपरोक्त कोड एक स्थिर सूचकांक से बहुत लाभान्वित होगा। हालांकि यह संकलित नहीं होगा क्योंकि स्थैतिक सूचकांक की अनुमति नहीं है। ऐसा क्यों है?


अगले मैं स्थिर वर्ग पर प्रत्यक्ष IEnumerable कार्यान्वयन चाहते हैं, तो मैं कर सकता हूँ foreach (var enum in Enum):)
nawfal

जवाबों:


72

सूचकांक संकेतन के लिए एक संदर्भ की आवश्यकता है this। चूंकि स्थिर विधियों में कक्षा के किसी विशेष उदाहरण का संदर्भ नहीं होता है, आप thisउनके साथ उपयोग नहीं कर सकते हैं, और परिणामस्वरूप आप स्थैतिक विधियों पर अनुक्रमणिका संकेतन का उपयोग नहीं कर सकते हैं।

आपकी समस्या का समाधान निम्नानुसार एक सिंगलटन पैटर्न का उपयोग कर रहा है:

public class Utilities
{
    private static ConfigurationManager _configurationManager = new ConfigurationManager();
    public static ConfigurationManager ConfigurationManager => _configurationManager;
}

public class ConfigurationManager
{
    public object this[string value]
    {
        get => new object();
        set => // set something
    }
}

अब आप Utilities.ConfigurationManager["someKey"]इंडेक्स अंकन का उपयोग करके कॉल कर सकते हैं ।


110
लेकिन इंडेक्सर को 'इस' का उपयोग क्यों करना पड़ता है? यह उदाहरण डेटा तक पहुँचने की जरूरत नहीं है
Malfist

80
Malfist की टिप्पणी के लिए +1। सिर्फ इसलिए कि यह उदाहरण के लिए "यह" का उपयोग करता है अनुक्रमणिका का मतलब यह नहीं है कि वे अन्य वाक्यविन्यास के साथ नहीं आ सकते हैं।
जॉन स्कीट

40
माना। आप सवाल से भीख मांग रहे हैं। आपने मूल रूप से कहा है कि इसकी अनुमति नहीं है क्योंकि इसकी अनुमति नहीं है। -1 क्योंकि सवाल यह था कि "इसकी अनुमति क्यों नहीं है?"
xr280xr

15
@ xr280xr +1 "भीख मांगने के सवाल" के सही इस्तेमाल के लिए :) प्लस मेरे पास भी यही शिकायत है।
रेडफिल्टर

14
-1 क्योंकि यह उत्तर मानता है कि एक स्थिर अनुक्रमणिका लागू होने पर वर्तमान संकेतन एकमात्र संभव संकेतन है। thisएक अनुक्रमणिका के उपयोग की आवश्यकता नहीं है, यह संभवतः अन्य खोजशब्दों के ऊपर चुना गया था क्योंकि यह सबसे अधिक समझ में आता था। एक स्थैतिक कार्यान्वयन के लिए, निम्नलिखित सिंटैक्स काफी व्यवहार्य हो सकता है public object static[string value]:। कीवर्ड thisको स्थिर संदर्भ में उपयोग करने की आवश्यकता नहीं है ।
आइंस्टीनसी

91

मेरा मानना ​​है कि इसे बहुत उपयोगी नहीं माना जाता था। मुझे लगता है कि यह भी शर्म की बात है - एक उदाहरण जिसका मैं उपयोग कर रहा हूं वह है एन्कोडिंग, जहां Encoding.GetEncoding("foo")हो सकता है Encoding["Foo"]। मुझे नहीं लगता कि यह बहुत बार आएगा , लेकिन इसके अलावा कुछ भी नहीं लगता कि यह थोड़ा असंगत है जो उपलब्ध नहीं है।

मुझे जांच करनी होगी, लेकिन मुझे संदेह है कि यह पहले से ही IL (इंटरमीडिएट भाषा) में उपलब्ध है।


6
इंटरमीडिएट भाषा - .NET के लिए विधानसभा भाषा की तरह।
जॉन स्कीट

15
मुझे यहां लाया गया है मेरे पास एक कस्टम वर्ग है जो एक स्थिर संपत्ति के माध्यम से मेरे आवेदन में उपयोग किए जाने वाले सामान्य मूल्यों के शब्दकोश को उजागर करता है। मैं GlobalState.State [KeyName] से सिर्फ GlobalState [KeyName] तक पहुंच को कम करने के लिए एक स्थिर सूचकांक का उपयोग करने की उम्मीद कर रहा था। अच्छा होता।
xr280xr

1
एफएलआईडब्ल्यूडब्ल्यू, एक संपत्ति के लिए आईएल में बदल रहा instanceहै staticऔर आईलैसम शिकायत में एक डिफ़ॉल्ट संपत्ति परिणाम पर गेट्टर विधि syntax error at token 'static'; मैं IL के मामलों में ध्यान केंद्रित करने में महान नहीं हूँ, लेकिन यह कम से कम एक प्रारंभिक संख्या की तरह लगता है।
अमेजिंग

8

काम के इर्द-गिर्द, आप एक सिंगलटन / स्टैटिक ऑब्जेक्ट पर एक इंस्टेंस इंडेकर को परिभाषित कर सकते हैं (कहते हैं कि कॉन्फ़िगरेशनमैन एक सिंगलटन है, बजाय स्टैटिक क्लास होने के):

class ConfigurationManager
{
  //private constructor
  ConfigurationManager() {}
  //singleton instance
  public static ConfigurationManager singleton;
  //indexer
  object this[string name] { ... etc ... }
}

1

मुझे स्टोर करने के लिए स्टेटिक इंडेक्सर की (अच्छी तरह से, और भी अच्छी तरह की) जरूरत थी, इसलिए मुझे कुछ अटपटा सा लगा।

जिस कक्षा में आप एक स्थिर इंडेक्सर (यहां: तत्व) चाहते हैं, उसी नाम + "डिक्ट" का एक उपवर्ग बनाएं। उक्त उपवर्ग के उदाहरण के रूप में इसे आसानी से स्थिर दें, और फिर अपना वांछित इंडेक्सर जोड़ें।

अंतिम, वर्ग को स्थैतिक आयात के रूप में जोड़ें (इसलिए उपवर्ग केवल स्थिर क्षेत्र को उजागर करता है)।

import static Element.ElementDict;

public class Element {
    // .... 
    private static readonly Dictionary<string, object> elemDict = new Dictionary<string, object>();
    public class ElementDict {
        public readonly static ElementDict element = new ElementDict();
        public object this[string key] {
            get => elemDict.TryGetValue(key, out object o) ? o : null;
            set => elemDict[key] = value;
        }
    }
}

और फिर आप इसका उपयोग या तो प्रकार के रूप में पूंजीकृत कर सकते हैं, या बिना शब्दकोश के कर सकते हैं:

var cnt = element["counter"] as int;
element["counter"] = cnt;

लेकिन अफसोस, अगर कोई वास्तव में "वैल्यू" के रूप में ऑब्जेक्ट का उपयोग करता है-तो, तो नीचे अभी भी कम (कम से कम घोषणा के रूप में) होगा, और तत्काल टाइपकास्टिंग भी प्रदान करेगा:

public static T load<T>(string key) => elemDict.TryGetValue(key, out object o) ? (T) o : default(T);
public static void store<T>(string key, T value) => elemDict[key] = value;

var cnt = Element.load<int>("counter");
Element.store("counter", cnt);

0

C # 6 में नए निर्माणों के साथ, आप गुण अभिव्यक्ति निकाय के साथ सिंगलटन पैटर्न को सरल बना सकते हैं। उदाहरण के लिए, मैंने निम्नलिखित शॉर्टकट का उपयोग किया है जो कोड-लेंस के साथ अच्छी तरह से काम करता है:

public static class Config
{
   public static NameValueCollection Get => ConfigurationManager.AppSettings;
}

इसमें पुराने कोड को अपग्रेड करने और अपनी एप्लिकेशन सेटिंग एक्सेस को एकीकृत करने के लिए प्रतिस्थापन-सक्षम होने का अतिरिक्त लाभ है।


-2

यह कीवर्ड क्लास के वर्तमान उदाहरण को संदर्भित करता है। स्थैतिक सदस्य कार्यों में यह सूचक नहीं होता है। इस कीवर्ड का उपयोग कंस्ट्रक्टर, इंस्टेंस मेथड्स, और एसेस एक्सेसर्स के सदस्यों को एक्सेस करने के लिए किया जा सकता है। ( msdn से प्राप्त )। चूंकि यह वर्ग के एक उदाहरण को संदर्भित करता है, यह स्थिर की प्रकृति के साथ संघर्ष करता है, क्योंकि स्थिर वर्ग की आवृत्ति से जुड़ा नहीं है।

एक वर्कअराउंड निम्नलिखित होगा जो आपको एक निजी शब्दकोश के विरुद्ध अनुक्रमणिका का उपयोग करने की अनुमति देता है ताकि आपको केवल एक नया उदाहरण बनाने की आवश्यकता हो और आप स्थैतिक भाग तक पहुंच सकें।

    public class ConfigurationManager 
{
    public ConfigurationManager()
    {
        // TODO: Complete member initialization
    }
    public object this[string keyName]
    {
        get
        {
                return ConfigurationManagerItems[keyName];
        }
        set
        {
                ConfigurationManagerItems[keyName] = value;
        }
    }
    private static Dictionary<string, object> ConfigurationManagerItems = new Dictionary<string, object>();        
}

यह आपको कक्षा के एक पूरे सदस्य को छोड़ने की अनुमति देता है और बस इसका एक उदाहरण बनाता है और इसे अनुक्रमित करता है।

    new ConfigurationManager()["ItemName"]

4
इसका एक दिलचस्प वर्कअराउंड, लेकिन 1) यह साइड-इफेक्ट्स (एक खाली इंस्टेंस ऑब्जेक्ट का निर्माण) का परिचय देता है, जिससे कुछ वातावरण में मेमोरी प्रेशर और विखंडन हो सकता है, 2) जो अतिरिक्त अक्षर बर्बाद new ()हो जाते हैं, उनका उपयोग किसी एकल के क्वालिफायर नाम के लिए किया जा सकता है। इसके बजाय, जैसे.Current
लॉरेंस वार्ड

1
जूलियट के जवाब की तरह , यह इस सवाल का जवाब नहीं देता है कि स्थिर सूचकांक क्यों समर्थित नहीं हैं। सबसे पहले, सवाल "स्थिर अनुक्रमणिका" शब्द को "कुछ ऐसा करता है जो thisकीवर्ड का उपयोग करता है" को प्रतिबंधित नहीं करता है , और दूसरा, thisवाक्यविन्यास public string this[int index]में कड़ाई से एक thisसूचक का उपयोग नहीं भी बोल रहा है (जैसा कि उदाहरण के तरीकों के शरीर में हो सकता है) , लेकिन टोकन का सिर्फ एक और उपयोग this। वाक्य-विन्यास थोड़ा उल्टा लगpublic static string this[int index] सकता है , लेकिन यह अभी भी असंदिग्ध होगा।
या मैपर

2
@ORMapper यह भी हो सकता है public static string class[int index]
जिम बेल्टर

मुझे लगता है कि मैं उलझन में हूँ मैंने सोचा कि 'यह कीवर्ड कक्षा की वर्तमान आवृत्ति को संदर्भित करता है। स्थैतिक सदस्य के कार्यों में यह सूचक नहीं होता है। ' यह समझा रहा था कि चूंकि इस सूचक के संदर्भ के लिए कोई वस्तु नहीं है, आप इसके संदर्भ का उपयोग नहीं कर सकते। और मैंने यह भी कहा कि एमएसडीएन वह था जो उस परिभाषा का उपयोग करता है। सार्वजनिक स्थैतिक स्ट्रिंग बनाम सार्वजनिक स्ट्रिंग कभी भी मेरे ज्ञान के अनुसार ओवरलैप नहीं होगी क्योंकि एक सामान्य प्रकार की वस्तु तक पहुंच होती है, जबकि दूसरा एक इंस्टेंस ऑब्जेक्ट तक पहुंच जाएगा।
12

-2

इसका कारण यह है कि यह समझना काफी कठिन है कि वास्तव में आप एक स्थिर सूचकांक के साथ क्या कर रहे हैं।

आप कहते हैं कि यह कोड एक स्थिर सूचकांक से लाभान्वित होगा, लेकिन क्या यह वास्तव में होगा? यह सब यह बदल जाएगा:

ConfigurationManager.editProperty(name, value);
...
value = ConfigurationManager.getProperty(name)

इस मामले में:

ConfigurationManager[name] = value
...
value = ConfigurationManager[name]

जो किसी भी तरह से कोड को बेहतर नहीं बनाता है; यह कोड की कई पंक्तियों से छोटा नहीं है, यह स्वत: पूर्ण होने के लिए धन्यवाद लिखना आसान नहीं है और यह कम स्पष्ट है, क्योंकि यह इस तथ्य को छुपाता है कि आप प्राप्त कर रहे हैं और कुछ सेट कर रहे हैं जिसे आप 'संपत्ति' कहते हैं और यह वास्तव में पाठक को मजबूर करता है इंडेक्सर रिटर्न या सेट्स के बारे में क्या है, इसके बारे में डॉक्यूमेंटेशन पढ़ें, क्योंकि यह किसी भी तरह से स्पष्ट नहीं है कि यह एक ऐसी संपत्ति है जिसे आप इंडेक्स कर रहे हैं, जबकि दोनों के साथ:

ConfigurationManager.editProperty(name, value);
...
value = ConfigurationManager.getProperty(name)

आप इसे ज़ोर से पढ़ सकते हैं और तुरंत समझ सकते हैं कि कोड क्या करता है।

याद रखें कि हम कोड लिखना चाहते हैं जो समझने में आसान (= तेज) है, न कि वह कोड जो लिखने में तेज है। उस गति की गलती न करें जिस पर आप जिस गति से परियोजनाओं को पूरा करते हैं, उसके साथ कोड को नीचे रख सकते हैं।


8
सहमत नहीं हैं। यह केवल एक वैचारिक बिंदु है। और कोड मेरी राय में बेहतर दिखता है, हालांकि यह केवल मेरी राय है।
१।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.