C#索引器的真实世界用例?

时间:2010-02-02 15:15:27

标签: c# indexer

我见过很多关于c#Indexers的例子,但它在现实生活中会以什么方式帮助我。

我知道C#guru如果不是一个严肃的功能就不会添加它,但我不能想到使用索引器的真实情况(不是foo bar的东西)。

注意:我意识到存在related question,但它对我没什么帮助。

14 个答案:

答案 0 :(得分:33)

我看索引器的方式是(正确或错误!),通过索引访问某些内容应该比以任何其他方式访问它更有效,因为在某种程度上,形状或形式,我正在使用其索引器的类存储某种形式的 index ,允许它以这种方式快速查找值。

经典示例是一个数组,当您使用代码myarray [3]访问数组的元素n时,编译器/解释器知道数组的大(内存方面)元素是多少并且可以将其视为一个数组偏离数组的开头。你也可以"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,但是,就像我说的那样......我总是认为“索引器”是一种从数据中获取数据的权宜之计。

答案 1 :(得分:24)

Skurmedel提到的最明显的例子是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

?现在,您需要编写索引器(通常在创建类似集合的类时)可能相对罕见,但我怀疑您经常使用它们。

答案 2 :(得分:9)

Microsoft has an example使用索引器将文件视为字节数组。

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

答案 3 :(得分:5)

假设您有一组对象,您希望能够通过除放置在集合中的顺序之外的其他对象进行索引。在下面的示例中,您可以看到如何使用某个对象的“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);}
  }
}

答案 4 :(得分:5)

一旦.NET得到泛型,我实现索引器(实现强类型集合)的最大原因就消失了。

答案 5 :(得分:3)

集合类型只是语法糖。我从来没有理由写这样的课。所以我认为它在“现实生活”中的使用非常罕见,因为使用它的类已经实现了。

答案 6 :(得分:3)

在ASP.Net中,有几个不同的时间使用索引器,例如从任何Request,Session或Application对象读取内容。我经常看到某些内容存储在Session或Application对象中,只是反复使用。

答案 7 :(得分:2)

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

答案 8 :(得分:2)

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

索引器是C#程序中允许Class表现为数组的元素。您可以将整个类用作数组。在此数组中,您可以存储任何类型的变量。变量存储在一个单独的位置,但由类名本身解决。为Integers,Strings,Boolean等创建索引器将是一个可行的想法。这些索引器将有效地作用于该类的对象。

让我们假设您已经创建了一个类索引器,用于存储班级中学生的卷号。此外,假设您已创建此类名为obj1的对象。当你说obj1 [0]时,你指的是第一个滚动的学生。同样,obj1 [1]指的是第二名学生。

因此,对象获取索引值以引用私有或公开存储在类中的Integer变量。假设你没有这个设施那么你可能会以这种方式引用(这会更长):

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

其中RollNumberVariable是Integer变量,它引用当前学生对象的Roll Number。

有关详细信息http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

答案 9 :(得分:1)

下面是我创建的视频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"];

干杯。

答案 10 :(得分:0)

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

使用System;

命名空间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;
        }
    }
}

}

答案 11 :(得分:0)

除了@ code-kings post。

此外,调用RollNumberVariable[0]将触发默认集合的索引器的行为。虽然索引器实际上是属性,但代表您在提取数据时编写自己的逻辑。您可以轻松地将大部分索引参数值委托给内部集合,但您也可以为某些索引值返回任意值。

只是一个例子 - 您可以拥有2个不同格式的内部集合,但外部用户将通过单个索引器(它将作为调度程序工作)与它们进行交互, 而那些收藏品将被隐藏。这几乎鼓励了封装原则。

答案 12 :(得分:0)

我正在尝试从序列文件中获取图像。我需要某种2D数组或锯齿状数组来保存像素值。我使用索引器而不是数组,因为循环索引器比循环遍历2D或锯齿状阵列更快。

答案 13 :(得分:0)

您可以使用索引器优雅地为非线程安全字典(或任何非线程安全集合)提供读/写多线程同步:

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(或任何其他并发集合)时非常有用。