Làm cách nào để quá tải toán tử dấu ngoặc vuông trong C #?


254

Ví dụ, DataGridView cho phép bạn làm điều này:

DataGridView dgv = ...;
DataGridViewCell cell = dgv[1,5];

nhưng đối với cuộc sống của tôi, tôi không thể tìm thấy tài liệu về toán tử index / ngoặc vuông. Họ gọi nó là gì? Nó được thực hiện ở đâu? Nó có thể ném không? Làm thế nào tôi có thể làm điều tương tự trong các lớp học của riêng tôi?

ETA: Cảm ơn tất cả các câu trả lời nhanh chóng. Tóm lại: tài liệu liên quan thuộc tài sản "Mục"; cách để quá tải là bằng cách khai báo một tài sản như thế nào public object this[int x, int y]{ get{...}; set{...} }; bộ chỉ mục cho DataGridView không ném, ít nhất là theo tài liệu. Nó không đề cập đến những gì xảy ra nếu bạn cung cấp tọa độ không hợp lệ.

Một lần nữa ETA: OK, mặc dù tài liệu không đề cập đến nó (Microsoft nghịch ngợm!), Nhưng hóa ra người lập chỉ mục cho DataGridView trên thực tế sẽ ném một ArgumentOutOfRangeException nếu bạn cung cấp nó với tọa độ không hợp lệ. Cảnh báo đúng.

Câu trả lời:


374

bạn có thể tìm thấy làm thế nào để làm điều đó ở đây . Nói tóm lại là:

public object this[int i]
{
    get { return InnerList[i]; }
    set { InnerList[i] = value; }
}

Nếu bạn chỉ cần một getter, cú pháp trong câu trả lời dưới đây cũng có thể được sử dụng (bắt đầu từ C # 6).


9
một nhận xét nhỏ: tùy thuộc vào những gì bạn đang làm, bạn có thể thấy nó phù hợp hơn để làm: get {return base [i]; } đặt {cơ sở [i] = giá trị; }
MikeBaz - MSFT

7
Đây không phải là quá tải toán tử. Nó là bộ chỉ mục
Destructor

5
Người lập chỉ mục, cũng có thể là một nhà điều hành đơn nguyên.
alan2here

1
Năm 2019, một câu trả lời mới nên được chọn, câu trả lời này . Quá tệ SO không có tính năng để đối phó với các câu trả lời không được chấp nhận, vì câu trả lời mới không gần để nhận được hơn 350 lượt upvote, mặc dù nó xứng đáng với chúng.
phút

@mins Tôi bao gồm một liên kết đến câu trả lời khác.
Ruben

41

Đó sẽ là thuộc tính vật phẩm: http://msdn.microsoft.com/en-us/l Library / 0ebtbkkc.aspx

Có lẽ một cái gì đó như thế này sẽ làm việc:

public T Item[int index, int y]
{ 
    //Then do whatever you need to return/set here.
    get; set; 
}

Cảm ơn rất nhiều! Nếu tôi có thể đặt hai câu trả lời, tôi cũng sẽ thêm câu trả lời của mình - không ai khác biết tìm Mục trong tài liệu ...
Bộ giải mã

5
Về cách thức triển khai, nó là "Mục", nhưng theo thuật ngữ C #, đó là "cái này"
Marc Gravell

1
Đúng, nhưng tôi đã hỏi "vì cuộc sống của tôi, tôi không thể tìm thấy tài liệu về toán tử chỉ số / dấu ngoặc vuông" - Ý tôi là khi bạn tìm một lớp thư viện trong MSDN, họ nói với bạn về toán tử ở đâu? Đó là lý do tại sao tôi thực hiện "ETA" cuối cùng về những gì nó ném - các tài liệu sai .
Bộ giải mã

26
Operators                           Overloadability

+, -, *, /, %, &, |, <<, >>         All C# binary operators can be overloaded.

+, -, !,  ~, ++, --, true, false    All C# unary operators can be overloaded.

==, !=, <, >, <= , >=               All relational operators can be overloaded, 
                                    but only as pairs.

&&, ||                  They can't be overloaded

() (Conversion operator)        They can't be overloaded

+=, -=, *=, /=, %=                  These compound assignment operators can be 
                                    overloaded. But in C#, these operators are
                                    automatically overloaded when the respective
                                    binary operator is overloaded.

=, . , ?:, ->, new, is, as, sizeof  These operators can't be overloaded

    [ ]                             Can be overloaded but not always!

Nguồn thông tin

Đối với khung:

public Object this[int index]
{

}

NHƯNG

Toán tử lập chỉ mục mảng không thể bị quá tải ; tuy nhiên, các loại có thể định nghĩa các bộ chỉ mục, các thuộc tính có một hoặc nhiều tham số. Các tham số của trình chỉ mục được đặt trong dấu ngoặc vuông, giống như các chỉ mục mảng, nhưng các tham số của trình chỉ mục có thể được khai báo là thuộc bất kỳ loại nào (không giống như các chỉ mục mảng, phải là tích phân).

Từ MSDN


vâng, nó có thể bị quá tải, miễn là chữ ký tham số khác nhau, chính xác như mọi hạn chế quá tải của phương thức khác
Charles Bretana

Nó có thể, nhưng không phải cho điều kiện tôi đã viết. Đó là từ MSDN. Kiểm tra nguồn nếu bạn không tin tôi
Patrick Desjardins

1
Xin lỗi nếu tôi đọc sai bài viết của bạn, nhưng bạn đang đề cập đến điều kiện gì?
Charles Bretana

+1 cho danh sách tiện dụng. FYI liên kết đã chết. (4 năm sau, tôi biết)
Mixxiphoid

Tôi muốn thêm rằng bạn có thể ghi đè cả kiểu truyền ẩn và kiểu rõ ràng trong C # ngay bây giờ.
Felype

9

Nếu bạn đang sử dụng C # 6 trở lên, bạn có thể sử dụng cú pháp thân biểu thức cho trình chỉ mục chỉ nhận:

public object this[int i] => this.InnerList[i];


6
public class CustomCollection : List<Object>
{
    public Object this[int index]
    {
        // ...
    }
}

5
Trên thực tế, điều này thực sự nguy hiểm - hiện bạn có hai triển khai cạnh tranh: bất kỳ ai có biến được nhập là Danh sách <T> hoặc IList <T> hoặc IList, v.v. sẽ không thực thi mã tùy chỉnh của bạn.
Marc Gravell

1
Đồng ý - nếu không có gì khác, không cần thiết phải lấy CustomCollection của bạn từ Danh sách, nhưng tôi đã không nhận ra nó thực sự nguy hiểm
Coderer

Nó vẫn sẽ thực thi mã tùy chỉnh, phải không? Việc bạn khai báo loại biến nào không quan trọng - đó là loại đối tượng quan trọng.
izb

1
Nhắc nhở thân thiện về đa hình C #: Điều đó xảy ra vì lớp cơ sở không khai báo việc triển khai của nó là ảo. Nếu nó được khai báo là ảo, mã tùy chỉnh sẽ được gọi trong mọi trường hợp.
almulo

1
Ngoài ra, mã này sẽ cung cấp cho bạn một cảnh báo trình biên dịch vì cả hai bộ chỉ mục đều không ảo. Trình biên dịch sẽ đề nghị bạn đủ điều kiện lập chỉ mục tùy chỉnh với newtừ khóa.
amoss

4

Đối với CLI C ++ (được biên dịch với / clr), xem liên kết MSDN này .

Nói tóm lại, một thuộc tính có thể được đặt tên "mặc định":

ref class Class
{
 public:
  property System::String^ default[int i]
  {
    System::String^ get(int i) { return "hello world"; }
  }
};

2

Dưới đây là một ví dụ trả về một giá trị từ một đối tượng Danh sách nội bộ. Nên cho bạn ý kiến.

  public object this[int index]
  {
     get { return ( List[index] ); }
     set { List[index] = value; }
  }

1

Nếu bạn có nghĩa là bộ chỉ mục mảng ,, Bạn quá tải chỉ bằng cách viết một thuộc tính bộ chỉ mục .. Và bạn có thể quá tải, (viết bao nhiêu tùy ý) các thuộc tính chỉ mục miễn là mỗi thuộc tính có một chữ ký tham số khác nhau

public class EmployeeCollection: List<Employee>
{
    public Employee this[int employeeId]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.EmployeeId == employeeId)
                    return emp;
            }

            return null;
        }
    }

    public Employee this[string employeeName]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.Name == employeeName)
                    return emp;
            }

            return null;
        }
    }
}

2
Đầu tiên, bạn có nghĩa là [], không phải () - tuy nhiên, việc cung cấp một tùy chỉnh (nhưng khác) này [int] trên một danh sách (IList / IList <T> / List <T>) khá nguy hiểm - và có thể dẫn đến các lỗi tinh vi giữa các phiên bản "int index" và "int workerId". Cả hai vẫn có thể gọi được.
Marc Gravell

và trên thực tế, tôi không nghĩ rằng mã tôi đã nhập ở trên sẽ biên dịch mà không cần thêm một câu lệnh mới hoặc ghi đè chính xác vì sự tồn tại của Danh sách <T> thực hiện [int] này. Bạn nói đúng về tiềm năng khi làm điều này, chỉ đơn giản là nó là ví dụ về quá tải chỉ mục.
Charles Bretana
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.