C# 索引器的真实用例?

发布于 2024-08-20 11:59:17 字数 240 浏览 13 评论 0原文

我看过很多 c# 索引器的示例,但它在现实生活中对我有什么帮助。

我知道如果这不是一个重要的功能,C# 大师就不会添加它,但我无法想象使用索引器的真实情况(不是 foo bar 的东西)。

注意:我意识到存在相关问题,但这对我没有帮助很多。

I've seen lot of examples for c# Indexers, but in what way will it help me in real life situations.

I know the C# guru wouldn't have added this if it wasn't a serious feature, but i cant think of a real world situation (not the foo bar stuff) to use indexers.

Note:I realize a related question exists, but it doesn't help me much.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

故事↓在人 2024-08-27 11:59:17

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

经典的例子是一个数组,当您使用代码 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,但是,就像我说的,.. 我一直认为“索引器”是从某些东西中获取数据的一种权宜之计.

The way I look at indexers is that (rightly or wrongly!), accessing something by index should be more efficient than accessing it any other way, because in some way, shape or form, the class whose indexer I'm using stores some form of index that allows it to quickly lookup values when accessed that way.

The classic example is an array, when you access element n of an array by using the code myarray[3], the compiler/interpreter knows how big (memory-wise) elements of the array are and can treat it as an offset from the start of the array. You could also "for(int i = 0; i < myarray.length; i++) { if (i = 3) then { .. do stuff } }" (not that you'd ever want to!), which would be less efficient. It also shows how an array is a bad example.

Say you had a collection class that stores, umm, DVDs, so:

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

Just my 2p, but, like I said,.. I've always considered an "indexer" as being an expedient way of getting data out of something.

戴着白色围巾的女孩 2024-08-27 11:59:17

Skurmedel 提到的最明显的例子是 ListDictionary。您更喜欢什么:

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

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

The most obvious examples, as mentioned by Skurmedel, are List<T> and Dictionary<TKey, TValue>. What would you prefer over:

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

? Now it may be relatively rare for you need to write an indexer (usually when you're creating a collection-like class), but I suspect you use them reasonably frequently.

完美的未来在梦里 2024-08-27 11:59:17

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

Microsoft has an example using an indexer to treat a file as an array of bytes.

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);
    }
}
喜你已久 2024-08-27 11:59:17

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

Let's say you have a collection of objects that you want to be able to index by something other than the order in which it was placed in a collection. In the example below, you can see how you could use the 'Location' property of some object and using the indexer, return all objects in the collection that match you location, or in the second example, all objects that contain a certain Count() of objects.

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);}
  }
}
揽月 2024-08-27 11:59:17

一旦 .NET 有了泛型,我实现索引器(实现强类型集合)的最大理由就消失了。

Once .NET got generics, the biggest reason for me to implement an indexer (to implement a strongly-typed collection) went away.

ら栖息 2024-08-27 11:59:17

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

It is just syntactical sugar for collection type classes. I never had a reason to write such a class. So I think there are very rare uses of it in "real life", because the classes using it are already implemented.

甜尕妞 2024-08-27 11:59:17

在 ASP.Net 中,有一些不同的时间使用索引器,例如从请求、会话或应用程序对象中读取某些内容。我经常看到一些东西存储在会话或应用程序对象中,只是为了一次又一次地使用。

In ASP.Net, there are a few different times where an indexer is used such as reading something from any of the Request, Session or Application objects. I've seen often where something is stored in either the Session or Application object only to be used again and again.

葬花如无物 2024-08-27 11:59:17
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();
        }
    }
}
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();
        }
    }
}
荒人说梦 2024-08-27 11:59:17

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

索引器是 C# 程序中的元素,允许类充当数组。您可以将整个类用作数组。在此数组中,您可以存储任何类型的变量。变量存储在单独的位置,但由类名本身寻址。为整数、字符串、布尔值等创建索引器将是一个可行的想法。这些索引器将有效地作用于类的对象。

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

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

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

其中 RollNumberVariable 是引用当前学生对象的卷编号的整数变量。

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

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

Indexers are elements in a C# program that allow a Class to behave as an Array. You would be able to use the entire class as an array. In this array you can store any type of variables. The variables are stored at a separate location but addressed by the class name itself. Creating indexers for Integers, Strings, Boolean etc. would be a feasible idea. These indexers would effectively act on objects of the class.

Lets suppose you have created a class indexer that stores the roll number of a student in a class. Further, lets suppose that you have created an object of this class named obj1. When you say obj1[0], you are referring to the first student on roll. Likewise obj1[1] refers to the 2nd student on roll.

Therefore the object takes indexed values to refer to the Integer variable that is privately or publicly stored in the class. Suppose you did not have this facility then you would probably refer in this way(which would be longer):

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

where RollNumberVariable would be the Integer variable that refers to the Roll Number of the current student object.

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

故事↓在人 2024-08-27 11:59:17

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

干杯。

Heres a video i have created http://www.youtube.com/watch?v=HdtEQqu0yOY and below is a detailed explanation about the same.

Indexers helps to access contained collection with in a class using a simplified interface. It’s a syntactic sugar.

For instance lets say you have a customer class with addresses collection inside it. Now let’s say we would like to like fetch the addresses collection by “Pincode” and “PhoneNumber”. So the logical step would be that you would go and create two overloaded functions one which fetches by using “PhoneNumber” and the other by “PinCode”. You can see in the below code we have two functions defined.

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

If you use indexer you can simplify the above code with something as shown in the below code.

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

Cheers.

幽梦紫曦~ 2024-08-27 11:59:17

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

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(或任何其他并发)时很有用收藏)。

You can use an indexer to elegantly provide read/write multi-threading synchronization to a non-thread safe dictionary (or any non-thread safe collection):

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

Useful especially when you don't want to use the heavyweight ConcurrentDictionary (or any other concurrent collection).

绝情姑娘 2024-08-27 11:59:17

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

}

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

using System;

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

}

鱼窥荷 2024-08-27 11:59:17

添加到@code-kings 帖子。

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

只是一个例子 - 您可以有 2 个以上不同格式的内部集合,但外部用户将通过单个索引器(这有点像调度程序)与它们交互,
而这些集合将被隐藏。这非常鼓励封装原则。

Addition to @code-kings post.

Moreover, calling RollNumberVariable[0] will trigger the behavior of the default collection's indexer. While indexers are actually properties, it's on your behalf to write your own logic when extracting data. You can easily delegate most of index-parameter value to the internal collection but you can also return any arbitrary value for certain index values.

Just an example - you can have 2+ internal collections in different format, but the external user will interact with them trough a single indexer (which will kinda work as a dispatcher),
while those collection will be hidden. This pretty much encourages the encapsulation principle.

李不 2024-08-27 11:59:17

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

I am trying to get images from a sequence file. I need some sort of a 2D array or a jagged array to hold the pixel values. I am using indexers instead of arrays because looping over indexers is faster than looping over 2D or jagged arrays.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文