Як я перевантажую оператор квадратної дужки в C #?


254

Наприклад, DataGridView дозволяє вам це робити:

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

але я не можу знайти документацію щодо оператора індексу / квадратних дужок. Як вони це називають? Де вона реалізована? Може кинути? Як я можу зробити те ж саме на власних заняттях?

ETA: Дякую за всі швидкі відповіді. Коротко: відповідна документація знаходиться у власності "Елемент"; спосіб перевантаження - це оголошення властивості типу public object this[int x, int y]{ get{...}; set{...} }; індексатор для DataGridView не кидає, принаймні згідно з документацією. У ньому не згадується, що станеться, якщо ви надаєте недійсні координати.

Знову ЗНО: Добре, хоча документація не згадує про це (пустотливий Microsoft!), Виявляється, що індексатор для DataGridView насправді викине ArgumentOutOfRangeException, якщо ви поставите його з недійсними координатами. Справедливе попередження.

Відповіді:


374

ви можете знайти, як це зробити тут . Коротше кажучи:

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

Якщо вам потрібен лише геттер, може бути використаний і синтаксис у відповіді нижче (починаючи з C # 6).


9
незначний коментар: залежно від того, що ви робите, ви можете вважати, що це доречніше: отримати {return base [i]; } встановити {base [i] = значення; }
MikeBaz - MSFT

7
Це не перевантаження оператора. Це індекс
Деструктор

5
Індексатор може також бути одинаковим оператором.
alan2тут

1
У 2019 році слід обрати нову відповідь, цю . Шкода, що ТА не має можливості мати справу з застарілими відповідями, оскільки новий не є близьким, щоб отримати 350+ оновлень, хоча це заслуговує на них.
хвилини

@mins Я включив посилання на іншу відповідь.
Рубен

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; 
}

Дуже дякую! Якби я міг встановити дві відповіді, я також додав би свою - ніхто більше не знав шукати Елемент у документації ...
Coderer

5
З точки зору того, як вона реалізується, це "Item", але в C # термінах, це "це"
Марк Гравелл

1
Правильно, але я запитав "за життя мене не можу знайти документацію про оператор індексу / квадратних дужок" - я мав на увазі, коли ви шукаєте клас бібліотеки в MSDN, де вони розповідають про оператора? Ось чому я зробив цю останню "ETA" про те, що вона кидає - документи помиляються .
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!

Джерело інформації

Для кронштейнів:

public Object this[int index]
{

}

АЛЕ

Оператор індексації масиву не може бути перевантажений ; однак типи можуть визначати індексатори, властивості, які приймають один або більше параметрів. Параметри індексатора укладені у квадратні дужки, як і індекси масиву, але параметри індексатора можуть бути оголошені будь-якими типами (на відміну від індексів масиву, які повинні бути інтегральними).

Від MSDN


так, він може бути перевантажений, якщо підпис параметра відрізняється, точно так само, як і обмеження щодо перевантаження будь-якого іншого методу
Чарльз Бретана

Може, але не за умови, про яку я написав. Це від MSDN. Перевірте джерело, якщо ви мені не вірите
Патрік Дежардінс

1
Вибачте, якщо я неправильно прочитав вашу публікацію, але про яку умову ви звертаєтесь?
Чарльз Бретана

+1 для зручного списку. FYI посилання загинула. (4 роки потому, я знаю)
Mixxiphoid

Я хотів би додати, що зараз ви можете змінити як неявне, так і явне кастинг типу в C #.
Феліпе

9

Якщо ви використовуєте C # 6 або новішу версію, ви можете використовувати синтаксис із вираженим виразом для індексатора лише отримання:

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


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

5
Насправді це справді небезпечно - тепер у вас є дві конкуруючі реалізації: будь-хто зі змінною, введеною як List <T> або IList <T> або IList тощо, не виконає ваш власний код.
Марк Гравелл

1
Домовились - якщо нічого іншого, не потрібно виводити свою CustomCollection зі списку, але я не зрозумів, що це насправді небезпечно
Coderer

Він все одно буде виконувати користувацький код, чи не так? Не має значення, який тип змінної ви заявляєте - це тип об'єкта, який має значення.
izb

1
Дружнє нагадування про поліморфізм C #. Це відбувається тому, що базовий клас не оголошує його реалізацію як віртуальну. Якби він був оголошений як віртуальний, користувацький код буде викликатися у кожному випадку.
almulo

1
Крім того, цей код подасть вам попередження про компілятор, оскільки обидва індексатори є невіртуальними. Компілятор запропонує вам визначити свій власний індексатор за newключовим словом.
амос

4

Для CLI C ++ (компілюється з / clr) див. Посилання MSDN .

Коротше кажучи, властивості можна надати ім'я "за замовчуванням":

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

2

Ось приклад повернення значення з внутрішнього об'єкта List. Слід дати вам ідею.

  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
По-перше, ви маєте на увазі це [], а не це () - однак надання спеціального (але іншого) цього [int] для чогось із списку (IList / IList <T> / List <T>) є досить небезпечним - і може призвести до тонких помилок між версіями "int index" та "int EmployId". Обидва все ще телефонують.
Марк Гравелл

і насправді, я не думаю, що код, який я ввів вище, скомпілюватиметься без додавання нового або перезаписуючого твердження саме через існування реалізації List <T> цього [int]. Ви маєте рацію щодо потенціалу, роблячи це, просто маючи на увазі це як приклад перевантаження індексатора.
Чарльз Бретана
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.