Как мне перегрузить оператор квадратных скобок в C#?

DataGridView, например, позволяет сделать это:

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

но хоть убей, я не могу найти документацию по оператору индекса / квадратной скобки. Как они это называют? Где это реализовано? Может его выкинуть? Как я могу делать то же самое в своих классах?

ETA: Спасибо за все быстрые ответы. Вкратце: соответствующая документация находится в свойстве «Предмет»; способ перегрузки - объявить свойство наподобие public object this[int x, int y]{ get{...}; set{...} }; индексатор для DataGridView не кидает, по крайней мере согласно документации. Не упоминается, что произойдет, если вы укажете неверные координаты.

ETA Again: Хорошо, хотя в документации об этом не упоминается (непослушный Microsoft!), Оказывается, что индексатор для DataGridView на самом деле выдаст исключение ArgumentOutOfRangeException, если вы предоставите ему недопустимые координаты. Справедливое предупреждение.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
261
0
130 677
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

да, он может быть перегружен, если подпись параметра отличается, точно так же, как и ограничения перегрузки любого другого метода

Charles Bretana 13.11.2008 22:40

Может, но не для того условия, которое я написал. Это из MSDN. Проверьте источник, если вы мне не верите

Patrick Desjardins 13.11.2008 23:13

Извините, если я неправильно прочитал ваш пост, но какое условие вы имеете в виду?

Charles Bretana 14.11.2008 00:00

+1 за удобный список. К вашему сведению ссылка умерла. (4 года спустя, я знаю)

Mixxiphoid 05.03.2013 01:04

Я хотел бы добавить, что теперь вы можете переопределить как неявное, так и явное приведение типов в C#.

Felype 15.09.2017 16:53
public class CustomCollection : List<Object>
{
    public Object this[int index]
    {
        // ...
    }
}

На самом деле это действительно опасно - теперь у вас есть две конкурирующие реализации: любой, у кого переменная введена как List <T> или IList <T> или IList и т. д., Не будет выполнять ваш собственный код.

Marc Gravell 14.11.2008 00:35

Согласен - по крайней мере, нет необходимости выводить CustomCollection из List, но я не осознавал, что это действительно опасно

Coderer 14.11.2008 17:58

Однако он по-прежнему будет выполнять собственный код, не так ли? Неважно, какой тип переменной вы объявляете - имеет значение тип объекта.

izb 11.11.2010 18:53

Если вы передадите объект функции, принимающей List <Object>, тогда пользовательский код не будет вызван

David Sykes 14.02.2012 13:07

Дружественное напоминание о полиморфизме C#: это происходит потому, что базовый класс не объявляет свою реализацию как виртуальную. Если бы он был объявлен как виртуальный, в каждом случае вызывался бы пользовательский код.

almulo 20.05.2015 15:03

Кроме того, этот код выдаст предупреждение компилятору, поскольку оба индексатора не являются виртуальными. Компилятор предложит вам указать в своем пользовательском индексаторе ключевое слово new.

amoss 18.05.2016 21:48
Ответ принят как подходящий

вы можете узнать, как это сделать здесь. Вкратце это:

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

Если вам нужен только геттер, можно также использовать синтаксис в ответ ниже (начиная с C# 6).

небольшой комментарий: в зависимости от того, что вы делаете, вам может показаться более подходящим: get {return base [i]; } установить {base [i] = значение; }

MikeBaz - MSFT 05.10.2012 01:58

Это не перегрузка оператора. Это индексатор

Destructor 12.05.2016 11:32

Индексатор также может быть унарным оператором.

alan2here 09.08.2016 15:27

В 2019 году следует выбрать новый ответ, Вот этот. Жаль, что у SO нет функции для работы с устаревшими ответами, поскольку новый еще не близок к тому, чтобы получить 350+ голосов, хотя он их заслуживает.

mins 03.07.2019 19:52

@mins Я добавил ссылку на другой ответ.

Ruben 08.07.2019 04:01

Это будет свойство элемента: 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; 
}

Большое спасибо! Если бы я мог задать два ответа, я бы добавил и ваш - никто другой не знал, что искать Item в документации ...

Coderer 13.11.2008 22:34

С точки зрения того, как это реализуется, это «Item», но в терминах C# это «this».

Marc Gravell 14.11.2008 00:43

Верно, но я спросил: «Да здравствует я, я не могу найти документацию по оператору индекса / квадратной скобки» - я имел в виду, когда вы просматриваете класс библиотеки в MSDN, где они говорят вам об операторе? Вот почему я сделал последнее "ETA" о том, что он бросает - это неправильный.

Coderer 14.11.2008 17:59

Вот пример, возвращающий значение из внутреннего объекта List. Должен дать вам идею.

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

Если вы имеете в виду индексатор массива, вы перегружаете его, просто записывая свойство индексатора. И вы можете перегружать (писать столько, сколько хотите) свойства индексатора, если каждый из них имеет другую сигнатуру параметра

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

Во-первых, вы имеете в виду this [], а не this () - однако предоставление специального (но другого) this [int] для чего-то, что является списком (IList / IList <T> / List <T>), довольно опасно - и может привести к незаметным ошибкам между версиями "int index" и "int employeeId". Оба по-прежнему можно отозвать.

Marc Gravell 14.11.2008 00:40

и на самом деле я не думаю, что код, который я ввел выше, будет компилироваться без добавления оператора new или override именно из-за существования List <T> реализации this [int]. Вы правы насчет потенциала, когда делаете это, просто имел в виду это как пример перегрузки индексатора.

Charles Bretana 14.11.2008 00:48

Для CLI C++ (скомпилированного с / clr) см. эта ссылка MSDN.

Вкратце, свойству можно присвоить имя «по умолчанию»:

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

Если вы используете C# 6 или новее, вы можете использовать синтаксис с выражением для индексатора только для получения:

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

Другие вопросы по теме