我已经看过很多关于 c# Indexers 的示例,但它在现实生活中会以何种方式帮助我。
我知道如果它不是一个严肃的功能,C# 大师就不会添加它,但我想不出现实世界的情况(不是 foo bar 的东西)来使用索引器。
注意:我意识到存在一个相关的问题,但这对我没有多大帮助。
我看待索引器的方式是(正确或错误!),通过索引访问某些内容应该比以任何其他方式访问它更有效,因为以某种方式,形状或形式,我正在使用其索引器的类存储某种形式的索引,允许它在以这种方式访问时快速查找值。
经典示例是数组,当您使用代码 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,但是,就像我说的,.. 我一直认为“索引器”是一种从某物中获取数据的权宜之计。
正如 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
? 现在,您可能需要编写一个索引器(通常在您创建一个类似集合的类时)相对较少,但我怀疑您会经常使用它们。
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);
}
}
假设您有一个对象集合,您希望能够按其在集合中的放置顺序以外的方式对其进行索引。在下面的示例中,您可以看到如何使用某个对象的“位置”属性并使用索引器,返回集合中与您的位置匹配的所有对象,或者在第二个示例中,所有包含某个 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);}
}
}
一旦 .NET 有了泛型,我实现索引器(实现强类型集合)的最大原因就消失了。
它只是集合类型类的语法糖。我从来没有理由写这样一门课。所以我认为在“现实生活”中很少使用它,因为使用它的类已经实现了。
在 ASP.Net 中,有几个不同的时间使用索引器,例如从任何请求、会话或应用程序对象中读取内容。我经常看到某些东西存储在 Session 或 Application 对象中,只是为了一次又一次地使用。
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();
}
}
}
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.in/2012/09/indexers-in-c-5.html
这是我创建的视频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"];
干杯。
您可以使用索引器优雅地为非线程安全字典(或任何非线程安全集合)提供读/写多线程同步:
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(或任何其他并发集合)时很有用。
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;
}
}
}
}
除了@code-kings 帖子。
此外,调用RollNumberVariable[0]
将触发默认集合的索引器的行为。虽然索引器实际上是属性,但它代表您在提取数据时编写自己的逻辑。您可以轻松地将大部分索引参数值委托给内部集合,但您也可以为某些索引值返回任意值。
只是一个例子 - 你可以有 2+ 个不同格式的内部集合,但外部用户将通过单个索引器与它们交互(这将作为一个调度程序工作),而这些集合将被隐藏。这非常鼓励封装原则。
我正在尝试从序列文件中获取图像。我需要某种二维数组或锯齿状数组来保存像素值。我使用索引器而不是数组,因为在索引器上循环比在 2D 或锯齿状数组上循环更快。