我见过很多关于c#Indexers的例子,但它在现实生活中会以什么方式帮助我。
我知道C#guru如果不是一个严肃的功能就不会添加它,但我不能想到使用索引器的真实情况(不是foo bar的东西)。
注意:我意识到存在related question,但它对我没什么帮助。
答案 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(或任何其他并发集合)时非常有用。