Tôi biết, tôi biết ... Câu trả lời của Eric Lippert cho loại câu hỏi này thường là " bởi vì nó không đáng với chi phí thiết kế, thực hiện, thử nghiệm và ghi lại nó ".
Nhưng tôi vẫn muốn có một lời giải thích tốt hơn ... Tôi đang đọc bài đăng trên blog này về các tính năng mới của C # 4 và trong phần về COM Interop, phần sau thu hút sự chú ý của tôi:
Nhân tiện, đoạn mã này sử dụng một tính năng mới nữa: thuộc tính được lập chỉ mục (hãy xem kỹ các dấu ngoặc vuông sau Phạm vi.) Nhưng tính năng này chỉ khả dụng cho COM interop; bạn không thể tạo các thuộc tính được lập chỉ mục của riêng mình trong C # 4.0 .
Được rôi nhưng tại sao ? Tôi đã biết và rất tiếc vì không thể tạo các thuộc tính được lập chỉ mục trong C #, nhưng câu này khiến tôi nghĩ lại về nó. Tôi có thể thấy một số lý do chính đáng để triển khai nó:
- CLR hỗ trợ nó (ví dụ:
PropertyInfo.GetValue
có mộtindex
tham số), vì vậy thật đáng tiếc chúng ta không thể tận dụng nó trong C # - nó được hỗ trợ cho COM interop, như được hiển thị trong bài viết (sử dụng điều phối động)
- nó được thực hiện trong VB.NET
- đã có thể tạo chỉ mục, tức là áp dụng chỉ mục cho chính đối tượng, vì vậy có lẽ sẽ không có vấn đề gì lớn nếu mở rộng ý tưởng cho các thuộc tính, giữ nguyên cú pháp và chỉ thay thế
this
bằng tên thuộc tính.
Nó sẽ cho phép viết những thứ như vậy:
public class Foo
{
private string[] _values = new string[3];
public string Values[int index]
{
get { return _values[index]; }
set { _values[index] = value; }
}
}
Hiện tại, cách giải quyết duy nhất mà tôi biết là tạo một lớp bên trong ( ValuesCollection
ví dụ) thực hiện một trình chỉ mục và thay đổi thuộc Values
tính để nó trả về một thể hiện của lớp bên trong đó.
Điều này rất dễ làm, nhưng khó chịu ... Vì vậy, có lẽ trình biên dịch có thể làm điều đó cho chúng ta! Một tùy chọn sẽ là tạo một lớp bên trong triển khai trình chỉ mục và hiển thị nó thông qua một giao diện chung chung:
// interface defined in the namespace System
public interface IIndexer<TIndex, TValue>
{
TValue this[TIndex index] { get; set; }
}
public class Foo
{
private string[] _values = new string[3];
private class <>c__DisplayClass1 : IIndexer<int, string>
{
private Foo _foo;
public <>c__DisplayClass1(Foo foo)
{
_foo = foo;
}
public string this[int index]
{
get { return _foo._values[index]; }
set { _foo._values[index] = value; }
}
}
private IIndexer<int, string> <>f__valuesIndexer;
public IIndexer<int, string> Values
{
get
{
if (<>f__valuesIndexer == null)
<>f__valuesIndexer = new <>c__DisplayClass1(this);
return <>f__valuesIndexer;
}
}
}
Nhưng tất nhiên, trong trường hợp đó thuộc tính thực sự sẽ trả về a IIndexer<int, string>
, và sẽ không thực sự là thuộc tính được lập chỉ mục ... Sẽ tốt hơn nếu tạo thuộc tính được lập chỉ mục CLR thực.
Bạn nghĩ sao ? Bạn có muốn xem tính năng này trong C # không? Nếu không, tại sao?