2

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

4

3 回答 3

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

于 2009-11-20T06:34:33.910 回答
1

这取决于观点,真的。

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

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

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

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

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

T get_Foo();
void set_Foo(T);

对于索引类型为I1, I2, ... 的索引属性:

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 导入的接口进行更改。

于 2009-11-20T06:56:18.730 回答
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;
}
于 2009-11-20T06:46:33.057 回答