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

发布于 2024-08-12 09:23:22 字数 20 浏览 5 评论 0原文

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

Is an indexer an extended version of a property?.

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

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

发布评论

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

评论(3

千里故人稀 2024-08-19 09:23:22

索引器允许像数组一样对类或结构的实例进行索引。索引器类似于属性,只是它们的访问器采用参数。

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

Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.

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

橙味迷妹 2024-08-19 09:23:22

这实际上取决于观点。

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

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

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

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

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

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# 中该类的索引器。非默认的索引属性只能从 C# 直接调用其访问器方法(get_Fooset_Foo)来访问 - 尽管这在 C# 4 中对于 COM 导入的接口会发生变化。

It depends on the viewpoint, really.

As far as C# is concerned, they are two orthogonal concepts. A class may have zero or more properties, and it may also have zero or more indexers. Properties are distinguished by their names, and indexers are overloaded by types of their arguments (similar to methods). They are similar in that either can have a gettor, a settor, or both, and in that assignment operators (including complex ones, such as +=) know how to handle them.

From CLS (and VB) perspective, there isn't such a thing as an indexer. There are only properties, and some of them are indexed, while others are not. An indexed property is the one where you have to provide additional values aside from the receiver itself to read the value, and receiver and new value to write the value - additional values are indices. There is also the concept of a "default property" - only one group of properties (all with the same name, but different index types) can be default.

From CLR perspective, a property by itself is just a name with a type and a bunch of methods associated with it; it doesn't really have any meaning on its own. It just shows where to find the methods when looking for accessors for the property of that name. There is no notion of default properties.

Now to reconcile those three things...

By CLS convention, plain properties are represented on CLR level by a property associated with methods with corresponding signatures, one for getter and one for setter. For a property Foo of type T, they would be:

T get_Foo();
void set_Foo(T);

And for an indexed property with indices of types I1, I2, ...:

T get_Foo(I1, I2, ...);
void set_Foo(I1, I2, ..., T);

To represent a default property, DefaultMemberAttribute is used to specify the name of that property.

C# reconciles its view with that of CLS by representing indexers as indexed properties. By default it uses the name Item for all such properties, but you can use IndexerNameAttribute to force it to name the property differently. It will also stick a DefaultMemberAttribute on the class with the indexer for that property, so it's seen as default property in VB (and other CLS-compliant languages that show indexed properties as such).

When consuming classes written in other languages, C# looks for DefaultMemberAttribute. If it's present, then indexed property referenced by it shows up as indexer on that class from C#. Indexed properties that aren't default are only accessible from C# by calling their accessor methods (get_Foo and set_Foo) directly - though this will change in C# 4 for COM-imported interfaces.

等往事风中吹 2024-08-19 09:23:22

索引器是第二层语法糖。对于属性,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;
}

Indexers are a second layer of syntactic sugar. With properties, get and set are transformed into method calls, those methods prefixed with get_/set_. In the case of indexers, indexers transformed into the method Item(). With any indexer argument being the first arguments of the methods. Also, get_/set_ is prefixed to the methods.

For those who prefer examples:

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

And here what happens with indexers:

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