मैं C # में स्क्वायर-ब्रैकेट ऑपरेटर को कैसे अधिभारित कर सकता हूं?


254

उदाहरण के लिए, DataGridView आपको ऐसा करने देता है:

DataGridView dgv = ...;
DataGridViewCell cell = dgv[1,5];

लेकिन मेरे जीवन के लिए मैं सूचकांक / वर्ग-ब्रैकेट ऑपरेटर पर प्रलेखन नहीं पा सकता हूं। वे इसे क्या कहते हैं? इसे कहां लागू किया गया है? क्या इसे फेंक सकते हैं? मैं अपनी कक्षाओं में एक ही काम कैसे कर सकता हूं?

ETA: सभी त्वरित उत्तर के लिए धन्यवाद। संक्षेप में: संबंधित दस्तावेज "आइटम" संपत्ति के तहत है; ओवरलोड करने का तरीका संपत्ति की घोषणा करके है public object this[int x, int y]{ get{...}; set{...} }; DataGridView के लिए अनुक्रमणिका कम से कम प्रलेखन के अनुसार नहीं फेंकती है। यदि आप अवैध निर्देशांक की आपूर्ति करते हैं तो यह उल्लेख नहीं करता है कि क्या होता है।

ETA अगेन: ठीक है, भले ही प्रलेखन इसका कोई उल्लेख नहीं करता है (शरारती Microsoft!), यह पता चला है कि DataGridView के लिए अनुक्रमणिका वास्तव में एक ArgumentOutOfRangeException फेंक देगा यदि आप इसे अवैध दिशानिर्देशों के साथ आपूर्ति करते हैं। निष्पक्ष चेतावनी।

जवाबों:


374

आप इसे यहाँ कैसे कर सकते हैं । संक्षेप में यह है:

public object this[int i]
{
    get { return InnerList[i]; }
    set { InnerList[i] = value; }
}

यदि आपको केवल उत्तर में सिंटैक्स की आवश्यकता है तो नीचे दिए गए सिंटैक्स का भी उपयोग किया जा सकता है (C # 6 से शुरू)।


9
एक मामूली टिप्पणी: आप जो कर रहे हैं, उसके आधार पर, आपको ऐसा करना अधिक उचित लग सकता है: प्राप्त {वापसी आधार [i]; } सेट {आधार [i] = मान; }
माइकबैज़ -

7
यह ऑपरेटर ओवरलोडिंग नहीं है। यह अनुक्रमणिका है
विनाशकारी

5
अनुक्रमणिका, साथ ही एक अपर संचालक हो सकता है।
alan2here

1
2019 में, एक नया उत्तर चुना जाना चाहिए, यह एक है । बहुत खराब एसओ के पास पदावनत उत्तरों से निपटने की सुविधा नहीं है, क्योंकि नया 350+ अपवॉट पाने के करीब नहीं है, हालांकि यह उनके योग्य है।
मिनट

@ मैं अन्य उत्तर के लिए एक लिंक शामिल करता हूं।
रुबेल

41

वह आइटम प्रॉपर्टी होगी: http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

शायद कुछ इस तरह काम करेगा:

public T Item[int index, int y]
{ 
    //Then do whatever you need to return/set here.
    get; set; 
}

आपका बहुत बहुत धन्यवाद! अगर मैं दो उत्तर निर्धारित कर सकता हूं, तो मैं आपको भी जोड़
दूंगा

5
यह कैसे लागू किया जाता है के संदर्भ में, यह है "आइटम", लेकिन सी # संदर्भ में, यह "यह" है
मार्क Gravell

1
ठीक है, लेकिन मैंने पूछा "मेरे जीवन के लिए मैं सूचकांक / वर्ग-ब्रैकेट ऑपरेटर पर प्रलेखन नहीं ढूंढ सकता" - मेरा मतलब था कि जब आप एमएसडीएन में एक पुस्तकालय वर्ग देखते हैं, तो वे आपको ऑपरेटर के बारे में कहां बताते हैं? इसलिए मैंने उस अंतिम "ईटीए" को बनाया जो इसे फेंकता है - डॉक्स गलत हैं
कोडर

26
Operators                           Overloadability

+, -, *, /, %, &, |, <<, >>         All C# binary operators can be overloaded.

+, -, !,  ~, ++, --, true, false    All C# unary operators can be overloaded.

==, !=, <, >, <= , >=               All relational operators can be overloaded, 
                                    but only as pairs.

&&, ||                  They can't be overloaded

() (Conversion operator)        They can't be overloaded

+=, -=, *=, /=, %=                  These compound assignment operators can be 
                                    overloaded. But in C#, these operators are
                                    automatically overloaded when the respective
                                    binary operator is overloaded.

=, . , ?:, ->, new, is, as, sizeof  These operators can't be overloaded

    [ ]                             Can be overloaded but not always!

सूचना का स्रोत

ब्रैकेट के लिए:

public Object this[int index]
{

}

परंतु

सरणी अनुक्रमण ऑपरेटर को अधिभारित नहीं किया जा सकता है ; हालाँकि, प्रकार इंडेक्सर्स, गुणों को परिभाषित कर सकते हैं जो एक या अधिक पैरामीटर लेते हैं। इंडेक्स पैरामीटर्स को वर्गाकार कोष्ठकों में संलग्न किया जाता है, जैसे कि ऐरे इंडेक्स, लेकिन इंडेक्स पैरामीटर को किसी भी प्रकार (ऐरे इंडेक्स के विपरीत, जो अभिन्न होना चाहिए) के रूप में घोषित किया जा सकता है।

से MSDN


हाँ, इसे अतिभारित किया जा सकता है, जब तक कि पैरामीटर हस्ताक्षर अलग-अलग होते हैं, बिल्कुल किसी अन्य विधि के अतिभार प्रतिबंधों की तरह
चार्ल्स ब्रेटाना

यह लिखा जा सकता है, लेकिन उस शर्त के लिए नहीं जो मैंने लिखा था। यह MSDN से है। स्रोत की जाँच करें यदि आप मुझ पर विश्वास नहीं करते हैं
पैट्रिक डेसजार्डिन

1
क्षमा करें यदि मैंने आपकी पोस्ट को गलत समझा, लेकिन आप किस स्थिति का उल्लेख कर रहे हैं?
चार्ल्स ब्रेटाना

आसान सूची के लिए +1। FYI करें लिंक की मृत्यु हो गई। (4 साल बाद, मुझे पता है)
मिक्सक्सिफ़ॉइड

मैं यह जोड़ना चाहता हूं कि आप C # में अब अंतर्निहित और स्पष्ट प्रकार-कास्टिंग दोनों को ओवरराइड कर सकते हैं।
फेल्पे

9

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

public object this[int i] => this.InnerList[i];


6
public class CustomCollection : List<Object>
{
    public Object this[int index]
    {
        // ...
    }
}

5
वास्तव में, यह वास्तव में खतरनाक है - अब आपके पास दो प्रतिस्पर्धात्मक कार्यान्वयन हैं: किसी भी चर के साथ जिसे लिस्ट <T> या IList <T> या IList आदि के रूप में टाइप किया गया है, जो आपके कस्टम कोड को निष्पादित नहीं करेगा।
मार्क Gravell

1
सहमत - अगर और कुछ नहीं है, तो यह आवश्यक नहीं है कि आप अपने CustomCollection को List से प्राप्त करें, लेकिन मुझे यह महसूस नहीं हुआ था कि यह वास्तव में खतरनाक था
Coderer

यह अभी भी कस्टम कोड को निष्पादित करेगा, है ना? इससे कोई फर्क नहीं पड़ता कि आप किस चर प्रकार की घोषणा करते हैं - यह उस वस्तु का प्रकार है जो मायने रखता है।
izb

1
C # बहुरूपता के अनुकूल अनुस्मारक: ऐसा इसलिए होता है क्योंकि आधार वर्ग अपने कार्यान्वयन को आभासी घोषित नहीं करता है। यदि इसे आभासी घोषित किया जाता है, तो कस्टम कोड को हर मामले में बुलाया जाएगा।
अल्मुलो

1
इसके अलावा, यह कोड आपको संकलक चेतावनी देगा क्योंकि दोनों अनुक्रमणिका गैर-आभासी हैं। कंपाइलर सुझाव देगा कि आप अपने कस्टम इंडेक्सर को newकीवर्ड के साथ क्वालिफाई करें ।
amoss

4

CLI C ++ के लिए (/ clr के साथ संकलित) इस MSDN लिंक को देखें

संक्षेप में, एक संपत्ति को "डिफ़ॉल्ट" नाम दिया जा सकता है:

ref class Class
{
 public:
  property System::String^ default[int i]
  {
    System::String^ get(int i) { return "hello world"; }
  }
};

2

यहाँ एक उदाहरण है जो आंतरिक सूची ऑब्जेक्ट से मान लौटाता है। आपको विचार देना चाहिए।

  public object this[int index]
  {
     get { return ( List[index] ); }
     set { List[index] = value; }
  }

1

यदि आप सरणी इंडेक्सर का मतलब रखते हैं, तो आप एक इंडेक्सर प्रॉपर्टी लिखकर उसे ओवरलोड करते हैं .. और आप ओवरलोड कर सकते हैं, (जितने चाहें उतने लिख सकते हैं) इंडेक्सर प्रॉपर्टीज जब तक प्रत्येक के पास एक अलग पैरामीटर सिग्नेचर होता है

public class EmployeeCollection: List<Employee>
{
    public Employee this[int employeeId]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.EmployeeId == employeeId)
                    return emp;
            }

            return null;
        }
    }

    public Employee this[string employeeName]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.Name == employeeName)
                    return emp;
            }

            return null;
        }
    }
}

2
सबसे पहले, आप इसका मतलब [], यह नहीं () - हालांकि, एक रिवाज (लेकिन अलग) प्रदान करना [यह] कुछ पर एक सूची (IList / IList <T> / सूची <T>) काफी खतरनाक है - और "इंट इंडेक्स" और "इंट कर्मचारीआईड" संस्करणों के बीच सूक्ष्म कीड़े हो सकते हैं। दोनों अभी भी कॉल करने योग्य हैं।
मार्क Gravell

और वास्तव में, मुझे नहीं लगता कि मैंने जो कोड ऊपर दर्ज किया है, वह इस सूची [<] के कार्यान्वयन <T> के अस्तित्व के कारण एक नया या ओवरराइड स्टेटमेंट जोड़ने के बिना संकलित करेगा। ऐसा करते समय आप क्षमता के बारे में सही हैं, बस इसका मतलब यह है कि ओवरलोडिंग इंडेक्स का उदाहरण।
चार्ल्स ब्रेटाना
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.