2012-02-08 33 views
8

Tôi có một danh sách tĩnh lớn về cơ bản là một bảng tra cứu, vì vậy tôi khởi tạo bảng trong mã.Sử dụng cú pháp trình khởi tạo bộ sưu tập trên các loại tùy chỉnh?

private class MyClass 
{ 
    private class LookupItem 
    { 
     public int Param1 { get; set; } 
     public int Param2 { get; set; } 
     public float Param2 { get; set; } 
     public float Param4 { get; set; } 
    } 

    private static List<LookupItem> _lookupTable = new List<LookupItem>() 
    { 
     new LookupItem() { Param1 = 1, Param2 = 2, Param3 = 3 Param4 = 4 }, 
     new LookupItem() { Param1 = 5, Param2 = 6, Param3 = 7 Param4 = 8 }, 
     //etc 
    } 
} 

Các thực LookupItem có nhiều tài sản hơn, vì vậy tôi đã thêm một constructor để cho phép một định dạng khởi động nhỏ gọn hơn:

private class MyClass 
{ 
    private class LookupItem 
    { 
     public int Param1 { get; set; } 
     public int Param2 { get; set; } 
     public float Param2 { get; set; } 
     public float Param4 { get; set; } 

     public LookupItem(int param1, int param2, float param3, float param4) 
     { 
      Param1 = param1; 
      Param2 = param2; 
      Param3 = param3; 
      Param4 = param4;  
     } 
    } 

    private static List<LookupItem> _lookupTable = new List<LookupItem>() 
    { 
     new LookupItem(1, 2, 3, 4), 
     new LookupItem(5, 6, 7, 8), 
     //etc 
    } 
} 

Những gì tôi thực sự muốn làm là sử dụng bộ sưu tập initialiser định dạng cho chính đối tượng để tôi có thể loại bỏ các new LookupItem() trên mọi dòng. ví dụ:

private static List<LookupItem> _lookupTable = new List<LookupItem>() 
{ 
    { 1, 2, 3, 4 }, 
    { 5, 6, 7, 8 }, 
    //etc 
} 

Điều này có thể? Tôi thích nghĩ rằng đó là vì KeyValuePair của một Dictionary<> có thể được khởi tạo theo cách này.

MSDN Hoa:

Collection initializers cho phép bạn chỉ định một hoặc yếu tố hơn intializers khi bạn khởi tạo một lớp bộ sưu tập mà thực hiện IEnumerable. Trình khởi tạo phần tử có thể là một giá trị đơn giản, biểu thức hoặc trình khởi tạo đối tượng. Bằng cách sử dụng bộ khởi tạo bộ sưu tập , bạn không phải chỉ định nhiều cuộc gọi đến phương thức Thêm của lớp trong mã nguồn của bạn; trình biên dịch thêm các cuộc gọi.

Điều này có nghĩa là tôi cần triển khai IEnumerable trên lớp LookupItem của tôi và trả lại từng thông số? Mặc dù lớp của tôi không phải là lớp tập hợp.

Trả lời

11

Tôi nghĩ bạn cần tạo bộ sưu tập tùy chỉnh thay vì Danh sách. Gọi nó là LookupItemTable, ví dụ. Cung cấp cho bộ sưu tập đó một phương thức Add (int, int, float, float) và có nó thực hiện IEnumerable. Ví dụ:

class LookupItem 
{ 
    public int a; 
    public int b; 
    public float c; 
    public float d; 
} 

class LookupItemTable : List<LookupItem> 
{ 
    public void Add(int a, int b, float c, float d) 
    { 
     LookupItem item = new LookupItem(); 
     item.a = a; 
     item.b = b; 
     item.c = c; 
     item.d = d; 
     Add(item); 
    } 
} 

private static LookupItemTable _lookupTable = new LookupItemTable { 
    { 1, 2, 3, 4 }, 
    { 5, 6, 7, 8 } 
}; 

Tôi hiện đã thử mã ở trên và có vẻ như nó hoạt động đối với tôi.

+0

Tuyệt vời. Cảm ơn nhiều. – GazTheDestroyer

4

Bạn đang cố gắng sử dụng một initializer bộ sưu tập trên danh sách riêng của mình, chứ không phải vào loại:

// Note the "new List<...>" part - that specifies what type the collection 
// initializer looks at... 
private static List<LookupItem> _lookupTable = new List<LookupItem>() 
{ 
    { 1, 2, 3, 4 }, 
    { 5, 6, 7, 8 }, 
} 

Vì vậy, nó đang tìm kiếm một phương pháp Add với bốn thông số trên List<T>, và điều đó không tồn tại.

Bạn sẽ phải triển khai bộ sưu tập riêng của mình để sử dụng trình khởi tạo bộ sưu tập tùy chỉnh. Trong khi bạn đang sử dụng List<T>, bạn đang mắc kẹt với các cuộc gọi constructor bạn đã có.

0

Điều này có nghĩa là tôi cần triển khai IEnumerable trên lớp LookupItem và trả về từng thông số? Mặc dù lớp của tôi không phải là lớp tập hợp.

Không, nó có nghĩa là List<LookupItem> thực hiện IEnumerable, đó là lý do tại sao bạn có thể viết

private static List<LookupItem> _lookupTable = new List<LookupItem>() 
{ 
    new LookupItem(1, 2, 3, 4), 
    new LookupItem(5, 6, 7, 8), 
    //etc 
} 

Nó cũng có nghĩa rằng nếu LookupItem của bạn là một bộ sưu tập mà thực hiện IEnumerable, bạn có thể viết:

private static List<LookupItem> _lookupTable = new List<LookupItem>() 
{ 
    new LookupItem { new Item(), new Item() }, 
    new LookupItem { new Item(), new Item() } 
} 
5

Sửa nhanh: Tự tạo List loại của riêng bạn với Add quá tải mà phải mất nhiều đối số:

class LookupList : List<LookupItem> { 
    public void Add(int Param1, int Param2, ... sometype ParamX) { 
     this.Add(new LookupItem() { Param1 = Param1, Param2 = Param2, ... ParamX = ParamX }); 
    } 
} 

Bây giờ làm việc chính xác như bạn muốn:

private static LookupList _lookupTable = new LookupList() {     
     {1,2,3,4},     
     {2,7,6,3}     
    }; 

câu trả lời More cơ bản:

Bạn đang trộn lên object initializerscollection initializers. Đặt đơn giản:

Trình khởi tạo đối tượng là một cú pháp cú pháp, trong nền gọi phương thức thuộc tính cho mỗi thuộc tính được đặt tên với giá trị được chỉ định.

Collection initializers là một thủ thuật cú pháp rằng, trong nền:

  • Đối với một loại Array: Điền vào mảng với các mục
  • Đối với bất kỳ loại nào khác, mà phải thực hiện IEnumerable: Gọi Phương pháp Add cho mỗi tập hợp khung phụ.

Đó là tất cả. Hãy xem xét ví dụ hack sau:

public class Hack : IEnumerable { 
    public int LuckyNumber { get; set; } 
    public double Total { get; private set; } 
    public void Add(string message, int operand1, double operand2, double operand3) { 
     Console.WriteLine(message); 
     this.Total += operand1 * operand2 - operand3; 
    } 
    public IEnumerator GetEnumerator() { throw new NotImplementedException(); } 
} 

class Program { 
    static void Main(string[] args) { 
     Hack h1 = new Hack() { 
      { "Hello", 1, 3, 2}, 
      { "World", 2, 7, 2.9} 
     }; 
     Console.WriteLine(h1.Total); 
     Hack h2 = new Hack() { LuckyNumber = 42 }; 
     Console.WriteLine(h2.LuckyNumber); 
    } 
} 

Bạn không bao giờ nên làm điều này trong một chương trình thực tế, nhưng tôi hy vọng xem xét ví dụ này và kết quả, đặc biệt là nếu bạn gỡ lỗi bước qua nó, sẽ giúp bạn hiểu được initializers rõ ràng và chọn một giải pháp tốt cho kịch bản hiện tại của bạn.

+0

'Bạn không bao giờ nên làm điều này trong một chương trình thực sự' - được rồi. Bạn nên làm gì trong một chương trình thực sự? Kịch bản: porting từ Java, và có một lớp có 3 'Add()' overloads và thực hiện 'IEnumerable '. Nếu tôi thực hiện 'ICollection ' Tôi sẽ có một loạt các phương thức 'Remove()', 'Clear()' mà tôi không muốn hoặc không cần. Có một giải pháp khác để làm cho nó rõ ràng hơn làm thế nào để sử dụng bộ khởi tạo bộ sưu tập bằng cách sử dụng Intellisense, hoặc là tài liệu văn bản tùy chọn duy nhất của tôi? – NightOwl888

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