C#中索引器和属性之间的关系是什么?

时间:2009-11-20 06:32:39

标签: c# properties indexer

索引器是属性的扩展版本吗?

3 个答案:

答案 0 :(得分:2)

索引器允许对类或结构的实例进行索引,就像数组一样。索引器类似于属性,除了它们的访问器接受参数。

class SampleCollection<T>
{
    // Declare an array to store the data elements.
    private T[] arr = new T[100];

    // Define the indexer, which will allow client code
    // to use [] notation on the class instance itself.
    // (See line 2 of code in Main below.)        
    public T this[int i]
    {
        get
        {
            // This indexer is very simple, and just returns or sets
            // the corresponding element from the internal array.
            return arr[i];
        }
        set
        {
            arr[i] = value;
        }
    }
}

// This class shows how client code uses the indexer.
class Program
{
    static void Main(string[] args)
    {
        // Declare an instance of the SampleCollection type.
        SampleCollection<string> stringCollection = new SampleCollection<string>();

        // Use [] notation on the type.
        stringCollection[0] = "Hello, World";
        System.Console.WriteLine(stringCollection[0]);
    }
}

http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx

答案 1 :(得分:1)

这取决于观点,真的。

就C#而言,它们是两个正交的概念。类可以具有零个或多个属性,并且它也可以具有零个或多个索引器。属性按名称区分,索引器按其参数类型重载(类似于方法)。它们的相似之处在于它们可以有一个gettor,一个settor或两者,并且在那个赋值运算符(包括复杂的运算符,如+=)知道如何处理它们。

从CLS(和VB)的角度来看,没有索引器这样的东西。只有属性,其中一些是索引的,而另一些则不是。索引属性是您必须提供除接收器本身之外的其他值以读取值的属性,以及用于写入值的接收器和新值 - 附加值是索引。还有“默认属性”的概念 - 只有一组属性(所有属性具有相同名称,但索引类型不同)可以是默认属性。

从CLR的角度来看,属性本身只是一个带有类型和一堆与之关联的方法的名称;它本身并没有任何意义。它只显示在查找该名称属性的访问器时查找方法的位置。没有默认属性的概念。

现在要调和这三件事......

通过CLS约定,普通属性在CLR级别由与具有相应签名的方法相关联的属性表示,一个用于getter,一个用于setter。对于Foo类型的属性T,它们将是:

T get_Foo();
void set_Foo(T);

对于索引类型为I1I2,...:

的索引属性
T get_Foo(I1, I2, ...);
void set_Foo(I1, I2, ..., T);

要表示默认属性,DefaultMemberAttribute用于指定该属性的名称。

C#通过将索引器表示为索引属性来协调其视图与CLS的视图。默认情况下,它对所有此类属性使用名称Item,但您可以使用IndexerNameAttribute强制它以不同方式命名属性。它还将使用该属性的索引器在类上粘贴DefaultMemberAttribute,因此它被视为VB中的默认属性(以及其他显示索引属性的符合CLS的语言)。

当使用其他语言编写的类时,C#会查找DefaultMemberAttribute。如果它存在,那么它引用的索引属性在C#中显示为该类的索引器。非默认的索引属性只能通过直接调用其访问器方法(get_Fooset_Foo)从C#访问 - 尽管这将在C#4中针对COM导入的接口进行更改。

答案 2 :(得分:0)

索引器是第二层语法糖。使用属性,get和set将转换为方法调用,这些方法以get_ / set_为前缀。在索引器的情况下,索引器转换为方法Item()。任何索引器参数都是方法的第一个参数。此外,get_ / set_是方法的前缀。

对于喜欢这些例子的人:

string foo;
public string Foo {
    get {
        return foo;
    }
    set {
        foo = value;
    }
}
// becomes
string foo;
public string get_Foo() {
    return foo;
}
public void set_Foo(string value) {
    foo = value;
}

在这里,索引器会发生什么:

string[] backingFoo;
public string this[int index] {
    get {
        return backingFoo[index];
    }
    set {
        backingFoo[index] = value;
    }
}
// becomes
string[] backingFoo;
public string get_Foo(int index) {
    return backingFoo[index];
}
public void set_Foo(int index, string value) {
    backingFoo[index] = value;
}