Реальные примеры использования для индексаторов C #? - PullRequest
44 голосов
/ 02 февраля 2010

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

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

Примечание.мне очень.

Ответы [ 14 ]

33 голосов
/ 02 февраля 2010

То, как я смотрю на индексаторы, заключается в том, что (правильно или неправильно!) Доступ к чему-либо по индексу должен быть более эффективным, чем доступ к нему любым другим способом, потому что в некотором роде или форме класс, чей индексатор я использую хранит некоторую форму 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, но, как я уже сказал, .. Я всегда считал «индексатор» удобным способом извлечения данных из чего-либо.

24 голосов
/ 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

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

9 голосов
/ 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);
    }
}
5 голосов
/ 02 февраля 2010

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

5 голосов
/ 02 февраля 2010

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

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);}
  }
}
3 голосов
/ 02 февраля 2010

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

3 голосов
/ 02 февраля 2010

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

2 голосов
/ 11 октября 2012

http://code -kings.blogspot.in / 2012/09 / индексаторах-в-с-5.html

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

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

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

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

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

Для получения более подробной информации http://code -kings.blogspot.in / 2012/09 / indexers-in-c-5.html

2 голосов
/ 03 мая 2011
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IndexerSample
{
    class FailSoftArray 
    {
        int[] a; // reference to underlying array
        public int Length; // Length is public
        public bool ErrFlag; // indicates outcome of last operation
        // Construct array given its size.
        public FailSoftArray(int size)
        {
            a = new int[size];
            Length = size;
        }
        // This is the indexer for FailSoftArray.
        public int this[int index] 
        {
        // This is the get accessor.
            get
            {
                if (ok(index))
                {
                    ErrFlag = false;
                    return a[index];
                }
                else
                {
                    ErrFlag = true;
                    return 0;
                }
            }
            // This is the set accessor.
            set
            {
                if (ok(index))
                {
                    a[index] = value;
                    ErrFlag = false;
                }
                else ErrFlag = true;
            }
        }
        // Return true if index is within bounds.
        private bool ok(int index)
        {
            if (index >= 0 & index < Length) return true;
            return false;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            FailSoftArray fs = new FailSoftArray(5);
            int x;
            // Show quiet failures.
            Console.WriteLine("Fail quietly.");
            for (int i = 0; i < (fs.Length * 2); i++)
                fs[i] = i * 10;
            for (int i = 0; i < (fs.Length * 2); i++)
            {
                x = fs[i];
                if (x != -1) Console.Write(x + " ");
            }
            Console.WriteLine();
            // Now, display failures.
            Console.WriteLine("\nFail with error reports.");
            for (int i = 0; i < (fs.Length * 2); i++)
            {
                fs[i] = i * 10;
                if (fs.ErrFlag)
                    Console.WriteLine("fs[" + i + "] out-of-bounds");
            }
            for (int i = 0; i < (fs.Length * 2); i++)
            {
                x = fs[i];
                if (!fs.ErrFlag) Console.Write(x + " ");
                else
                    Console.WriteLine("fs[" + i + "] out-of-bounds");
            }
            Console.ReadLine();
        }
    }
}
1 голос
/ 18 апреля 2013

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

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

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

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

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

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

Приветствие.

...