2010-08-23 53 views
11

Tôi muốn tạo thuộc tính trong C# để đặt hoặc trả về một thành viên riêng lẻ của một mảng. Hiện nay, tôi có điều này:Thuộc tính trưng bày các phần tử mảng trong C#

private string[] myProperty; 
public string MyProperty[int idx] 
{ 
    get 
    { 
     if (myProperty == null) 
      myProperty = new String[2]; 

     return myProperty[idx]; 
    } 
    set 
    { 
     myProperty[idx] = value; 
    } 
} 

Tuy nhiên, tôi nhận được lỗi biên dịch sau:

Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type.

+0

http://www.codeproject.com/KB/cs/csharptips.aspx –

Trả lời

12

Làm thế nào về điều này: viết một lớp chỉ thực hiện một điều và một thứ: cung cấp quyền truy cập ngẫu nhiên vào các thành phần của một số bộ sưu tập được lập chỉ mục cơ bản. Tặng số một chỉ số this này.

Đối với các thuộc tính mà bạn muốn cung cấp quyền truy cập ngẫu nhiên, chỉ cần trả lại phiên bản của lớp chỉ mục này.

thực hiện Trivial:

public class Indexer<T> 
{ 
    private IList<T> _source; 

    public Indexer(IList<T> source) 
    { 
     _source = source; 
    } 

    public T this[int index] 
    { 
     get { return _source[index]; } 
     set { _source[index] = value; } 
    } 
} 

public static class IndexHelper 
{ 
    public static Indexer<T> GetIndexer<T>(this IList<T> indexedCollection) 
    { 
     // could cache this result for a performance improvement, 
     // if appropriate 
     return new Indexer<T>(indexedCollection); 
    } 
} 

Refactoring vào mã của bạn:

private string[] myProperty; 
public Indexer<string> MyProperty 
{ 
    get 
    { 
     return myProperty.GetIndexer(); 
    } 
} 

này sẽ cho phép bạn có nhiều thuộc tính được lập chỉ mục như bạn muốn, mà không cần phải phơi bày những thuộc tính với giao diện IList<T> .

5

Bạn phải sử dụng this như tên tài sản cho indexers.

+0

Nếu tôi có nhiều hơn một thì sao? –

+0

Bạn sẽ phải làm cho MyProperty trả về một số loại danh sách có thể lập chỉ mục. Nếu bạn cần kiểm soát chặt chẽ, bạn có thể muốn thực hiện nó cho mình. – recursive

0

Bạn cần sử dụng trình chỉ mục. Nó hoạt động hơi khác một chút. Xem ví dụ:

public class Node 
{ 
    public Node this[int offset] 
    { 
     get { return localList[offset]; } 
    } 
} 

Lưu ý: Bạn chỉ được phép có một người lập chỉ mục cho mỗi lớp. Lý do là nó quá khó hiểu với trình biên dịch như ý nghĩa, vì vậy bạn chỉ được phép một.

Bạn cũng có thể làm điều này:

private static int[] _widget = new int[Counter]; 
public static int [] Widget 
{ 
    get { return _widget; } 
    set { _widget = value; } 
} 

...

for (int i = 0; i < MyClass.Counter; i++) 
{ 
    MyClass.Widget[i] = i; 
} 

... 
double _newWidget5 = MyClass.Widget[5]; 
// and so on... 
5

C# cho phép chỉ có một tài sản mỗi lớp được lập chỉ mục, vì vậy bạn buộc phải sử dụng này.

+0

không đúng. Bạn có thể có nhiều hơn một chỉ mục miễn là chữ ký khác nhau, tức là loại của những gì được sử dụng làm giá trị chỉ mục khác nhau. –

+0

Mọi thứ đã thay đổi rồi. Ban đầu hạn chế như vậy đã tồn tại. Bạn có nhớ gửi cú pháp mới và cho chúng tôi biết khi nào nó được thêm vào ngôn ngữ không? – joekoyote

+0

có lẽ chúng ta đang nói về các mục đích chéo: bạn có thể khai báo 'public int this [string index]' cùng với 'public int this [int index]' và chúng có thể làm hai thứ hoàn toàn khác nhau. Tôi sẽ nói rằng đó là nhiều hơn một thuộc tính được lập chỉ mục. –

1

Một lựa chọn là để recode nó như sau:

private string[] myProperty = new string[2]; 
public string[] MyProperty 
{ 
    get 
    { 
     return myProperty; 
    } 
    set 
    { 
     myProperty = value; 
    } 
} 

Nó sẽ biên dịch, nhưng nó đã thiết lập riêng của mình về các vấn đề (FxCop sẽ hét lên về nó, nhưng nó có thể dẫn bạn đến những lựa chọn khác) .

+0

Đây là giao diện mạnh hơn giao diện ban đầu, chỉ cho phép sửa đổi các phần tử. Điều này thực sự cho phép thay thế mảng cơ bản thông qua tập hợp. –

1

Bạn có thể làm một cái gì đó như thế này:

class Indexers 
{ 
    private string[] _strings = new [] {"A","B"}; 
    private int[] _ints = new[] { 1, 2 }; 

    public string[] Strings 
    { 
     get{ return _strings;} 
    } 

    public int[] Ints 
    { 
     get{ return _ints;} 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Indexers indexers = new Indexers(); 

     int a1 = indexers.Ints[0]; 
     string a2 = indexers.Strings[0]; 
    } 
} 
2

Bạn có thể sử dụng nó theo cách này:

private string[] myProp; 
    public string[] MyProp 
    { 
     get 
     { 
      if (myProp == null) 
      { 
       myProp = new String[2]; 
      } 
      return myProp; 
     } 

     set 
     { 
      myProp = value; 
     } 
    } 

Và nó có thể acces myProp [1] như MyProp [1] Ví dụ

2

Hiển thị mảng của bạn thông qua thuộc tính chỉ đọc có thể đáp ứng nhu cầu của bạn.Vì bạn không muốn cho phép mã khác để gán mảng như vậy, không có nhu cầu về một setter công cộng:

private string[] myProperty; 
public string[] MyProperty 
{ 
    get 
    { 
     if (myProperty == null) 
     { 
      myProperty = new String[2]; 
     } 

     return myProperty; 
    } 
} 

Sau đó, bạn có thể viết mã như vậy:

theObject.MyProperty[1] = "some string"; 

.. .Nhưng bạn không thể thay thế các mảng chính:

theObject.MyProperty = new string[2]; // will not compile 
1

Thứ nhất, trong lĩnh vực khai tránh dư thừa séc:

private string[] myProperty = new string[2]; 

Bạn có thể thực hiện một số chỉ mục thông qua quá tải theo loại đầu vào:

public string this[int index] 
{ 
    get 
    { 
     return myProperty[index]; 
    } 
    set 
    { 
     myProperty[index] = value; 
    } 
} 

public object this[object a, object b] // different input type(s) (and different return type) 
{ 
    get 
    { 
     // do other stuff 
    } 
} 
1

C# cung cấp không có cơ chế tích hợp để tạo tài sản được lập chỉ mục. Bạn có thể sử dụng trình chỉ mục cấp lớp (sử dụng ký hiệu this[int index]), nhưng không có gì giống như vậy ở cấp thuộc tính.

Một tùy chọn là tạo lớp trợ giúp với trình chỉ mục và sử dụng lớp này làm loại thuộc tính. Xem một số example trên MSDN.

Các vấn đề liên quan