Примеры использования индексаторов C # в реальном мире?

Я видел много примеров для индексаторов C #, но каким образом это поможет мне в реальных жизненных ситуациях.

Я знаю, что гуру C # не добавил бы это, если бы это не было серьезной функцией, но я не могу думать о реальной ситуации (не о барахле foo), чтобы использовать индексаторы.

Примечание. Я понимаю, что существует связанный с этим вопрос, но он мне не помогает много.


person Vivek Bernard    schedule 02.02.2010    source источник
comment
Кроме типа списка, типа LinkedList, типа словаря или других коллекций? ;) Часто, когда у вас есть список чего-либо, считается полезным предоставить индексатор, поэтому можно использовать myList [k] вместо myList.Get (k) или VB-версию myList.Item (k)   -  person Skurmedel    schedule 02.02.2010
comment
@Skurmedel Пожалуйста, объясните, я явно что-то упускаю   -  person Vivek Bernard    schedule 02.02.2010
comment
Итак, у меня есть класс, который содержит поле col, которое является коллекцией, и когда мне нужно получить доступ к определенному значению в col, это будет, когда я буду использовать индексатор   -  person Vivek Bernard    schedule 02.02.2010
comment
См. Также stackoverflow.com/questions/1764943/   -  person Robert Harvey    schedule 02.02.2010
comment
Да, если ваш класс имитирует какое-либо хранилище или содержит отдельные фрагменты данных, которые вы можете захотеть получить. String имеет индексатор, поэтому вы можете выполнить str [1], чтобы получить второй символ. FontStorage [key] может иметь смысл, Font [key], вероятно, нет. Как хранятся данные, обычно не имеет значения, но интерфейс (внешний вид / представление) определяет, имеет ли смысл индексатор. Тем не менее, я использую их очень редко, но иногда они пригодятся. Я сделал оболочку ASP.NET Cache, где Cache [key] имел смысл, реальный сценарий;)   -  person Skurmedel    schedule 02.02.2010
comment
не забудьте DataSet, DataTable, DataColumn и DataRow. все они тоже используют индексаторы!   -  person Muad'Dib    schedule 02.02.2010
comment
@Skurmedel, вы могли бы опубликовать это как ответ. +1 точно.   -  person Vivek Bernard    schedule 02.02.2010


Ответы (13)


Я смотрю на индексаторы так (правильно или неправильно!), Доступ к чему-либо по индексу должен быть более эффективным, чем доступ к нему любым другим способом, потому что в некотором роде, форме или форме, класс, индексатор которого я использую, хранит некоторую форму index, что позволяет ему быстро искать значения при доступе таким образом.

Классическим примером является массив, когда вы обращаетесь к элементу n массива с помощью кода myarray [3], компилятор / интерпретатор знает, насколько велики (с точки зрения памяти) элементы массива, и может рассматривать его как смещение от начало массива. Вы также можете "for(int i = 0; i < myarray.length; i++) { if (i = 3) then { .. do stuff } }" (хотя вам и не хотелось бы!), Что было бы менее эффективно. Это также показывает, что массив является плохим примером.

Допустим, у вас есть класс коллекции, в котором хранятся, ммм, DVD, так что:

public class DVDCollection
{
    private Dictionary<string, DVD> store = null;
    private Dictionary<ProductId, string> dvdsByProductId = null;

    public DVDCollection()
    {
        // gets DVD data from somewhere and stores it *by* TITLE in "store"
        // stores a lookup set of DVD ProductId's and names in "dvdsByProductid"
        store = new Dictionary<string, DVD>();
        dvdsByProductId = new Dictionary<ProductId, string>();
    }

    // Get the DVD concerned, using an index, by product Id
    public DVD this[ProductId index]  
    {
       var title = dvdsByProductId[index];
       return store[title];
    }
}

Просто мой 2p, но, как я уже сказал, ... Я всегда считал "индексатор" наиболее целесообразным способом извлечения данных из чего-либо.

person Rob    schedule 02.02.2010

Самыми очевидными примерами, как упоминал Скурмедель, являются List<T> и Dictionary<TKey, TValue>. Что бы вы предпочли:

List<string> list = new List<string> { "a", "b", "c" };
string value = list[1]; // This is using an indexer

Dictionary<string, string> dictionary = new Dictionary<string, string>
{
    { "foo", "bar" },
    { "x", "y" }
};
string value = dictionary["x"]; // This is using an indexer

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

person Jon Skeet    schedule 02.02.2010
comment
Означает ли это, что несколько индексаторов не могут существовать. или другими словами они могут быть перегружены? - person Vivek Bernard; 02.02.2010
comment
@ Вивек Бернард: Их можно перегружать. - person OregonGhost; 02.02.2010

В Microsoft есть пример использования индексатора для обработки файл как массив байтов.

public byte this[long index]
{
    // Read one byte at offset index and return it.
    get 
    {
        byte[] buffer = new byte[1];
        stream.Seek(index, SeekOrigin.Begin);
        stream.Read(buffer, 0, 1);
        return buffer[0];
    }
    // Write one byte at offset index and return it.
    set 
    {
        byte[] buffer = new byte[1] {value};
        stream.Seek(index, SeekOrigin.Begin);
        stream.Write(buffer, 0, 1);
    }
}
person Robert Harvey    schedule 02.02.2010
comment
Я думаю, что это хороший пример, потому что индексаторы позволяют извлекать или хранить элементы, тем самым имитируя поведение массива. В этом случае он используется для сохранения (сериализации и десериализации) данных, скрывая сложность доступа к файлу. Это может быть и база данных. Я также видел, что сериализатор .NET JSON использует его для имитации массивов в стиле JavaScript, позволяя использовать строки и числа в качестве индексов в том же классе (путем перегрузки индексатора). В конце концов, это, конечно, синтаксический сахар, но он помогает упростить мысли и сделать их более удобочитаемыми (и более удобными в использовании). - person Matt; 11.12.2015

Допустим, у вас есть коллекция объектов, которую вы хотите индексировать не в том порядке, в котором она была размещена в коллекции. В приведенном ниже примере вы можете увидеть, как вы можете использовать свойство Location некоторого объекта и с помощью индексатора вернуть все объекты в коллекции, которые соответствуют вашему местоположению, или, во втором примере, все объекты, которые содержат определенный Count ( ) объектов.

class MyCollection {

  public IEnumerable<MyObject> this[string indexer] {
    get{ return this.Where(p => p.Location == indexer); }
  }

  public IEnumerable<MyObject> this[int size] {
    get{ return this.Where(p => p.Count() == size);}
  }
}
person scottm    schedule 02.02.2010

Когда в .NET появились дженерики, у меня исчезла основная причина реализовать индексатор (для реализации строго типизированной коллекции).

person Daniel Pratt    schedule 02.02.2010
comment
Зачем уменьшать потребность в индексаторе с помощью дженериков? Или вы имеете в виду, что у вас больше не было необходимости писать собственные коллекции? - person Skurmedel; 02.02.2010

Это просто синтаксический сахар для классов типов коллекций. У меня никогда не было причин писать такой класс. Так что я думаю, что в «реальной жизни» он используется очень редко, потому что классы, использующие его, уже реализованы.

person Stefan Steinegger    schedule 02.02.2010
comment
Не забывайте, что редкость одного человека - требование другого. Хотя они являются синтаксическим сахаром ... это можно сказать о большей части фреймворка. (Enum, Свойства, Перегрузка оператора, Linq, WCF и т. Д.) - person Matthew Whited; 02.02.2010
comment
@Matthew: есть ли разница между использованием индексатора и метода GetElement? Индексатор короче в использовании. - person Stefan Steinegger; 02.02.2010
comment
Также нет разницы между использованием Property и метода GetProperty. Если вы используете скомпилированный код, это происходит на заднем плане. Каждое ключевое слово, которое мы используем (помимо кодов операций для ЦП или среды выполнения), является формой синтаксического сахара ... и я, например, люблю сахар. Например ... когда вы используете индексатор в C #, вы объявляете его в классе с ключевым словом this. В VB.Net вы просто выбираете свойство и добавляете входной параметр. - person Matthew Whited; 02.02.2010
comment
@Matthew: Я сказал, что это бесполезно или что мне это не нравится? Я просто сказал, что в этом нет ничего особенного, просто чтобы было удобнее использовать классы типов коллекций. Я не знаю, что вы хотите мне сказать. - person Stefan Steinegger; 03.02.2010
comment
Я тоже не хотел сказать. Ваш ответ просто походил на многие, которые я видел о ненужных и нежелательных функциях. (Наряду со строками людей, которые жалуются, что был добавлен синтаксис LINQ.) Если вы все сторонники индексаторов, мы согласны :) Я говорю, используйте их там, где вам нужно или вы хотите их использовать. Все это всего лишь инструменты, которые помогут облегчить нашу жизнь как разработчикам. - person Matthew Whited; 03.02.2010

В ASP.Net несколько раз используется индексатор, например, чтение чего-либо из любого объекта запроса, сеанса или приложения. Я часто видел, как что-то хранится в объекте Session или Application только для того, чтобы использовать его снова и снова.

person JB King    schedule 02.02.2010

http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

Индексаторы - это элементы в программе C #, которые позволяют классу вести себя как массив. Вы могли бы использовать весь класс как массив. В этом массиве вы можете хранить любые типы переменных. Переменные хранятся в отдельном месте, но адресуются самим именем класса. Создание индексаторов для целых чисел, строк, логических значений и т. Д. Было бы осуществимой идеей. Эти индексаторы будут эффективно воздействовать на объекты класса.

Предположим, вы создали индексатор класса, в котором хранится номер ученика в классе. Далее, предположим, что вы создали объект этого класса с именем obj1. Когда вы говорите obj1 [0], вы имеете в виду первого учащегося в списке. Точно так же obj1 [1] относится ко второму учащемуся в списке.

Следовательно, объект принимает индексированные значения для ссылки на целочисленную переменную, которая хранится в классе в частном или публичном порядке. Предположим, у вас нет этого средства, тогда вы, вероятно, будете ссылаться таким образом (что будет дольше):

obj1.RollNumberVariable[0]
obj1.RollNumberVariable[1]. 

где RollNumberVariable будет целочисленной переменной, которая относится к номеру ролика текущего объекта студента.

Для получения дополнительных сведений http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

person code-kings    schedule 11.10.2012

Вот видео, которое я создал http://www.youtube.com/watch?v=HdtEQqu0yOY и ниже приводится подробное объяснение того же.

Индексаторы помогают получить доступ к содержащейся коллекции в классе с помощью упрощенного интерфейса. Это синтаксический сахар.

Например, допустим, у вас есть класс клиентов с коллекцией адресов внутри него. Теперь предположим, что мы хотели бы получить коллекцию адресов по «Пинкоду» и «Телефонному номеру». Таким образом, логичным шагом будет создание двух перегруженных функций, одна из которых будет извлекаться с помощью «PhoneNumber», а другая - «PinCode». В приведенном ниже коде вы можете видеть, что у нас определены две функции.

Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");

Если вы используете индексатор, вы можете упростить приведенный выше код чем-нибудь, как показано в приведенном ниже коде.

Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];

Ваше здоровье.

person Shivprasad Koirala    schedule 18.04.2013
comment
IMHO пример не лучший, вот почему: индексаторы должны иметь семантику массива, поэтому ожидается, что клиенты [1001] вернут клиента, а не другой тип, например Address. В вашем случае лучше использовать getAddress для передачи правильного намерения. В противном случае я бы назвал класс, реализующий индексатор, как Адреса, а затем получил бы Адрес как Адреса [1001] - person Sudhanshu Mishra; 25.08.2016

Вы можете использовать индексатор, чтобы элегантно обеспечить многопоточную синхронизацию чтения / записи для непоточно-безопасного словаря (или любой небезопасной коллекции):

internal class ThreadSafeIndexerClass
{
    public object this[int key]
    {
        get
        {
            // Aquire returns IDisposable and does Enter() Exit() on a certain ReaderWriterLockSlim instance
            using (_readLock.Aquire()) 
            {
                object subset;
                _dictionary.TryGetValue(key, out foundValue);
                return foundValue;
            }
        }
        set
        {
            // Aquire returns IDisposable and does Enter() Exit() on a certain ReaderWriterLockSlim instance
            using (_writeLock.Aquire())
                _dictionary[key] = value;
        }
    }
}

Полезно, особенно если вы не хотите использовать тяжелый ConcurrentDictionary (или любую другую параллельную коллекцию).

person brakeroo    schedule 01.11.2016

http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

используя Систему;

пространство имен Indexers_Example

{

class Indexers
{

    private Int16[] RollNumberVariable;

    public Indexers(Int16 size)
    {
        RollNumberVariable = new Int16[size];

        for (int i = 0; i < size; i++)
        {
            RollNumberVariable[i] = 0;
        }
    }

    public Int16 this[int pos]
    {
        get
        {
            return RollNumberVariable[pos];
        }
        set
        {
            RollNumberVariable[pos] = value;
        }
    }
}

}

person code-kings    schedule 11.10.2012

Дополнение к сообщению @ code-kings.

Более того, вызов RollNumberVariable[0] вызовет поведение индексатора коллекции по умолчанию. Хотя индексаторы на самом деле являются свойствами, вы должны написать собственную логику при извлечении данных. Вы можете легко делегировать большую часть значения параметра индекса внутренней коллекции, но вы также можете вернуть любое произвольное значение для определенных значений индекса.

Просто пример - у вас может быть 2+ внутренних коллекций в разном формате, но внешний пользователь будет взаимодействовать с ними через один индексатор (который будет работать как диспетчер), в то время как эта коллекция будет скрыта. Это в значительной степени поддерживает принцип инкапсуляции.

person Artur Udod    schedule 11.10.2012

Я пытаюсь получить изображения из файла последовательности. Мне нужен какой-то 2D-массив или зубчатый массив для хранения значений пикселей. Я использую индексаторы вместо массивов, потому что цикл по индексаторам быстрее, чем цикл по 2D или неровным массивам.

person user2330678    schedule 04.08.2014