2010-01-06 37 views
11

Làm một số đọc mã và stumbled khi đoạn này mà tôi chưa từng thấy trước đây:C# điểm hoặc lợi ích của một người lập chỉ mục là gì?

public SomeClass { 
    public someInterface this[String strParameter] { 
    get { 
     return SomeInternalMethod(strParameter); 
    } 
    } 
} 

Dường như nó được gọi như sau:

SomeClass _someClass = new SomeClass(); 
SomeInterface returnedValue = _someClass["someString"]; 

Tôi quan tâm đến nơi chức năng này sẽ thích hợp hoặc ý định viết theo phong cách này. Ví dụ tại sao điều này sẽ được ưa thích hơn chỉ đơn giản là gọi chức năng?

+1

Nó là tự nhiên, thanh lịch, làm hài lòng mắt, tăng cường sự hiểu biết. Các cuộc gọi phương thức rất nhàm chán. Kiểm tra điều này: http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html –

Trả lời

19

Xem đặc điểm kỹ thuật ngôn ngữ, phần 10,9, trong đó nêu:

Một Indexer là thành viên cho phép một đối tượng được lập chỉ mục trong cùng một cách như một mảng.

Indexer và tài sản là rất giống nhau trong khái niệm, nhưng khác nhau về các cách sau:

  • Một tài sản được xác định bởi tên của nó, trong khi một indexer được xác định bởi chữ ký của mình.
  • Thuộc tính được truy cập thông qua một tên đơn giản (§7.5.2) hoặc truy cập thành viên (§7.5.4), trong khi phần tử chỉ mục được truy cập thông qua truy cập phần tử (§7.5.6.2).
  • Thuộc tính có thể là thành viên tĩnh, trong khi người lập chỉ mục luôn là thành viên cá thể.
  • Trình truy cập của thuộc tính tương ứng với phương thức không có tham số, trong khi đó trình truy cập của trình chỉ mục tương ứng với phương thức có cùng danh sách tham số chính thức như trình chỉ mục.
  • Một bộ truy nhập được thiết lập tương ứng với một phương thức có giá trị được đặt tên duy nhất, trong khi bộ truy nhập được thiết lập của một trình chỉ mục tương ứng với một phương thức có cùng danh sách tham số chính thức như chỉ mục.
  • Đây là lỗi biên dịch cho trình truy cập chỉ mục để khai báo biến cục bộ có cùng tên với tham số chỉ mục.
  • Trong khai báo thuộc tính ghi đè, thuộc tính kế thừa được truy cập bằng cách sử dụng cú pháp base.P, trong đó P là tên thuộc tính. Trong một khai báo chỉ mục trọng, người lập chỉ mục kế thừa được truy cập bằng cơ sở cú pháp [E], trong đó E là một danh sách các biểu thức được phân cách bằng dấu phẩy.
+2

Tôi biết tôi không nên chiếm đoạt điều này, nhưng có thể bạn có thể viết blog về lý do tại sao không có Lập chỉ mục tĩnh? Tôi đã bị sốc khi tôi thấy rằng họ không tồn tại, chỉ vì nó là một cách tốt đẹp, viết tắt. (Trước khi Jon đưa ra Mã hóa tốt ["UTF8"] Ví dụ :)) –

+3

Tôi vừa kiểm tra lưu trữ ghi chú thiết kế và không có gì trong đó biện minh cho quyết định không có các chỉ mục tĩnh. Do đó, tôi phải quay trở lại với lời giải thích thông thường của tôi vì sao chúng tôi không có một tính năng: không ai nghĩ rằng đó là một ý tưởng đủ tốt để tiêu tiền để biến nó thành sự thật. Tôi tưởng tượng rằng cùng một lời giải thích này cũng giải thích tại sao các chỉ mục không thể là chung chung. –

+0

Cool :) Điều tuyệt vời về giải thích "mặc định" là nó không hoàn toàn đóng cửa cánh cửa này. Tôi không biết làm thế nào "nặng" tính năng này là (và tôi sẽ không loại bỏ bản thân mình bằng cách nói "nhưng nó chỉ là một thay đổi nhỏ!" Mà không biết làm thế nào trình biên dịch và CLR thực sự làm việc), nhưng nó tốt hơn "Chúng tôi đã không làm vì X, Y và Z làm cho nó không thể thực hiện nó ". –

5

Trong nhiều trường hợp, cú pháp 'chỉ mục' có ý nghĩa rất nhiều. Nó đặc biệt hữu ích nếu SomeClass đại diện cho một số loại bộ sưu tập.

3

Tính năng này cho phép bạn thực hiện tra cứu mảng liên kết (kiểu "từ điển"), giống như bạn đã đề cập trong câu hỏi của mình.

Và đó là toàn bộ vấn đề. Một số người thích điều đó, đặc biệt là những người đến từ các ngôn ngữ được xây dựng bằng ngôn ngữ như Python hoặc PHP

0

Nó thực hiện toán tử chỉ mục [ ].

0

Đó là quá tải của nhà điều hành. Hữu ích nếu bạn đang viết một lớp thu thập ví dụ, nơi nó sẽ có ý nghĩa để truy cập nó bằng cách sử dụng ký hiệu mảng, ví dụ: bộ sưu tập [someIndex].

Tất nhiên bạn có thể viết một hàm sưu tập.GetElement (someIndex) tương đương, nhưng đó là một kiểu dáng/khả năng đọc.

3

Các "này" từ khóa là một indexer

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

"Indexer cho phép các trường hợp của một lớp học hoặc struct được lập chỉ mục giống như mảng. Indexer giống thuộc tính ngoại trừ việc accessors họ lấy thông số."

+0

Ý của bạn là gì: từ khóa "này" là một người lập chỉ mục? – spender

0

Bạn cũng có thể sử dụng phương pháp này trong lớp cặp khóa-giá trị.

Tôi không chắc lớp tương tự là gì trong C#, nhưng trong C++ STL, có lớp bản đồ nơi bạn gọi phương thức với SomeObject["key"] và nó sẽ trả về "giá trị" được liên kết với khóa đó.

+0

Lớp tương tự trong C# là System.Collections.Generic.Dictionary (ngoại trừ từ điển sử dụng tra cứu mã băm, trong khi ánh xạ bản đồ các phím) –

0

Được gọi là Trình lập chỉ mục, chúng cho phép bạn sử dụng Danh sách <>, ArrayList, Dictionary <> và tất cả các bộ sưu tập khác sử dụng cú pháp mảng.

Đó chỉ là đường cú pháp, nhưng nó mang lại một số khả năng đọc khi sử dụng đúng.

1

Bạn có thể đã tình cờ một cái gì đó tương tự như trước đây:

var myList = new List<string>(); 
myList.Add("One"); 
myList.Add("Two"); 
myList.Add("Three"); 

for(int i = 0; i < myList.Count; i++) { 
    string s = myList[i]; 
} 

Các indexer là "chìa khóa chính" của một đối tượng mà thực hiện một bộ sưu tập. Nó chỉ là một cách viết tắt để viết một hàm như .GetValue (index) - cú pháp đường, nếu bạn muốn. Nhưng nó cũng làm cho ý định rõ ràng.

13

Có vẻ như rất nhiều câu trả lời đang tập trung vào những gì một người lập chỉ mục, chứ không phải lý do bạn muốn sử dụng nó.

Theo như tôi đang quan tâm, đây là động lực để sử dụng một indexer:

Bạn đang làm việc trên một lớp một bộ sưu tập của một số loại, nhưng bạn muốn lớp xuất hiện cho người dùng (người tiêu dùng của lớp) như thể nó một bộ sưu tập.

Ví dụ tốt nhất mà tôi có thể nghĩ là lớp DataRow trong ADO.NET. Nếu bạn muốn lấy giá trị của ô thứ năm của DataRow, bạn có thể sử dụng DataRow.Item[4] hoặc DataRow[4]. Dạng thứ hai là một phím tắt thuận tiện và hợp lý, và nó cho thấy khá độc đáo tại sao bạn muốn sử dụng một trình chỉ mục. Đối với người dùng, DataRow có thể được coi là một tập hợp các ô (mặc dù nó thực sự nhiều hơn thế), do đó, bạn có thể nhận và đặt giá trị ô trực tiếp, mà không cần phải nhớ rằng bạn thực sự nhận/thiết lập Item.

Hy vọng điều đó sẽ hữu ích.

0

Theo tôi, nó chỉ là một cú pháp thuận tiện. đâu bạn sẽ KHÔNG sử dụng nó:

public SomeClass { 
    private int[] nums; 
    public GetVal this[int ind] { 
    get { 
     return nums[ind]; // this is pointless since array is already indexed 
    } 
    } 
} 

bạn sẽ hưởng lợi đâu từ nó:

public Matrix { 
    private Dictionary<string, double> matrixData; // Matrix indecies, value 
    public double this[int row, int col] { 
    get { 
     return matrixData[string.Format("{0},{1}", row, col)]; 
    } 
    } 
} 

Như bạn có thể thấy, đối với một số lý do, dữ liệu của bạn là một từ điển được lập chỉ mục với một chuỗi khóa và bạn muốn gọi số này bằng hai số nguyên chưa có và vẫn không muốn thay đổi loại dữ liệu của mình:

Matrix m = new Matrix(); 
... 
Console.WriteLine(m[1,2]); 
Các vấn đề liên quan