C # 'daki köşeli parantez operatörünü nasıl aşırı yüklerim?


254

Örneğin, DataGridView bunu yapmanıza izin verir:

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

ama hayatım boyunca dizin / köşeli parantez operatörü ile ilgili belgeleri bulamıyorum. Buna ne diyorlar? Nerede uygulanır? Fırlatabilir mi? Aynı şeyi kendi sınıflarımda nasıl yapabilirim?

ETA: Tüm hızlı cevaplar için teşekkürler. Kısaca: ilgili belgeler "Eşya" özelliğinin altındadır; aşırı yüklenmenin yolu, aşağıdaki gibi bir özellik bildirmektir public object this[int x, int y]{ get{...}; set{...} }; DataGridView dizinleyicisi en azından belgelere göre atmaz. Geçersiz koordinatlar sağlarsanız ne olacağından bahsetmez.

Yine ETA: Tamam, belgeler bundan bahsetmese de (yaramaz Microsoft!), Geçersiz koordinatlara sahip olursanız DataGridView dizinleyicisinin aslında bir ArgumentOutOfRangeException kuracağı ortaya çıkıyor. Adil uyarı.

Yanıtlar:


374

nasıl yapılacağını burada bulabilirsiniz . Kısacası:

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

Yalnızca bir alıcıya ihtiyacınız varsa sözdizimi aşağıdaki cevaptaki de kullanılabilir (C # 6'dan başlayarak).


9
küçük bir yorum: ne yaptığınıza bağlı olarak, bunu yapmak için daha uygun bulabilirsiniz: get {return base [i]; } set {base [i] = değer; }
MikeBaz - MSFT

7
Bu operatörün aşırı yüklenmesi değil. İndeksleyici
Yıkıcı

5
Dizin oluşturucu, tekli bir operatör de olabilir.
alan2here

1
2019'da yeni bir cevap seçilmelidir, bu . Çok kötü SO, kullanımdan kaldırılmış cevaplarla başa çıkma özelliğine sahip değildir, çünkü yeni olan 350+ upvotes almaya yakın değildir, ancak hak ediyor.
dakika

@mins Diğer yanıta bir bağlantı ekledim.
Ruben

41

İtem özelliği şu olurdu: http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

Belki böyle bir şey işe yarayabilir:

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

Çok teşekkürler! İki cevap ayarlayabilseydim, sizinkini de
eklerdim

5
Nasıl uygulandığı açısından, "Öğe", ancak C # açısından, bu "bu"
Marc Gravell

1
Doğru, ama sordum "benim hayatım için dizin / köşeli parantez operatörü ile ilgili belgeleri bulamıyorum" - MSDN'de bir kütüphane sınıfına baktığınızda, operatör hakkında nereden bahsediyorlar? Bu yüzden attığı şey hakkında son "ETA" yı yaptım - dokümanlar yanlış .
Coderer

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!

Bilginin kaynağı

Parantez için:

public Object this[int index]
{

}

FAKAT

Dizi indeksleme operatörü aşırı yüklenemiyor ; ancak, türler dizinleyicileri, bir veya daha fazla parametre alan özellikleri tanımlayabilir. Dizin oluşturucu parametreleri, dizin dizinleri gibi köşeli parantez içine alınır, ancak dizin oluşturucu parametreleri herhangi bir türde (tümleşik olması gereken dizi dizinlerinin aksine) olarak bildirilebilir.

Gönderen MSDN


evet, parametre imzası farklı olduğu sürece, diğer herhangi bir yöntemin aşırı yükleme kısıtlamaları gibi aşırı yüklenebilir
Charles Bretana

Yazabilirim ama olabilir. MSDN'den. Bana inanmıyorsanız kaynağı kontrol edin
Patrick Desjardins

1
Yayınınızı yanlış okuduğumda üzgünüm, ancak hangi koşuldan bahsediyorsunuz?
Charles Bretana

Kullanışlı liste için +1. FYI bağlantı koptu. (4 yıl sonra biliyorum)
Mixxiphoid

Şimdi C # hem örtük hem de açık tip döküm geçersiz kılabilirsiniz eklemek istiyorum.
Felype

9

C # 6 veya daha yenisini kullanıyorsanız, yalnızca get indexer için ifade gövdeli sözdizimini kullanabilirsiniz:

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


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

5
Aslında, bu gerçekten tehlikelidir - artık iki rakip uygulamanız var: değişken <T> veya IList <T> veya IList vb.
Marc Gravell

1
Kabul edildi - başka bir şey yoksa, CustomCollection'ınızı Listeden türetmek gerekli değildir, ancak bunun gerçekten tehlikeli olduğunu fark
etmemiştim

Yine de özel kodu yürütecek, değil mi? Hangi değişken türünü bildirdiğiniz önemli değildir - önemli olan nesnenin türüdür.
izb

1
C # polimorfizminin kolay hatırlatıcısı: Bunun nedeni, temel sınıfın uygulamayı sanal olarak bildirmemesidir. Sanal olarak bildirilirse, özel kod her durumda çağrılır.
almulo

1
Ayrıca, bu kod her iki dizinleyici sanal olmadığından derleyici uyarısı verecektir. Derleyici, özel dizinleyicinizi newanahtar kelimeyle nitelendirmenizi önerir .
amoss

4

CLI C ++ (/ clr ile derlenir) için bu MSDN bağlantısına bakın .

Kısacası, bir mülke "varsayılan" adı verilebilir:

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

2

Aşağıda, dahili List nesnesinden bir değer döndüren bir örnek verilmiştir. Size fikir vermeli.

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

1

Eğer dizi indeksleyicisini kastediyorsanız, sadece bir indeksleyici özelliği yazarak aşırı yüklersiniz .. Ve her biri farklı bir parametre imzası olduğu sürece indeksleyici özelliklerini aşırı yükleyebilirsiniz.

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
Birincisi, bu [], bunu değil () değil - ancak, bu [int] 'i liste olan bir şey (IList / IList <T> / Liste <T>) için özel (ancak farklı) sağlamak oldukça tehlikelidir - ve "int index" ve "int workerId" sürümleri arasında küçük hatalara yol açabilir. Her ikisi de hala çağrılabilir.
Marc Gravell

ve aslında, yukarıda girdiğim kodun tam olarak bu [int] Listesinin <T> uygulanmasının varlığı nedeniyle yeni veya geçersiz kılma ifadesi eklemeden derleneceğini düşünmüyorum. Bunu yaparken potansiyel konusunda haklısınız, sadece aşırı yük endeksine örnek olarak kastedildi.
Charles Bretana
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.