2012-04-12 7 views
6

Tôi đến từ JavaScript và tôi biết rằng { } là một đối tượng theo nghĩa đen, không cần phải yêu cầu cuộc gọi new Object; Tôi tự hỏi nếu nó giống với C# trong phần {"id",id}, {"saveChangesError",true}.Tính năng C# nào cho phép sử dụng ký pháp kiểu "đối tượng theo nghĩa đen"?

Tôi biết có hai tính năng C# ở đây, hãy quan tâm để giải thích cho tôi nhiều hơn về chúng là gì?

new RouteValueDictionary() 
{ //<------------------------------[A: what C# feature is this?] -------|| 
    {"id",id}, //<------------------[B: what C# feature is this also?] || 
    {"saveChangesError",true}            || 
}); //<------------------------------------------------------------------|| 
+0

Đó là ma thuật chỉ đặc biệt trong C# để tự động gọi cho một số phương pháp ('Add' đặc biệt) * sau * các đối tượng đã được tạo. –

+0

Đối với người trả lời: có thể * khởi tạo thuộc tính * được trộn lẫn với * khởi tạo bộ sưu tập *? (Điều này sẽ có mặt trong việc giải thích cấu trúc "bên ngoài", vì nó có thể là: 'new Foo {Bar = Quz} '.) –

+0

@pst: Không, ngay cả trong VB.NET, kỳ lạ đủ ... – Ryan

Trả lời

8

Đó là một tính năng duy nhất - collection initializers. Giống như khởi tạo đối tượng, nó chỉ có thể được sử dụng như là một phần của biểu thức khởi tạo đối tượng, nhưng về cơ bản nó gọi là Add với bất kỳ đối số nào.

var list = new List<int> { 1, 2, 3 }; 

Xem phần 7.6.10.3 của thông số C# 4 để biết thêm thông tin.

Lưu ý rằng trình biên dịch đòi hỏi hai điều của một kiểu cho nó được sử dụng để khởi tạo bộ sưu tập:

  • Nó phải thực hiện IEnumerable, mặc dù trình biên dịch không tạo ra bất kỳ cuộc gọi đến GetEnumerator
  • Nó phải có quá tải thích hợp cho một phương pháp Add

Ví dụ:

using System; 
using System.Collections; 

public class Test : IEnumerable 
{ 
    static void Main() 
    { 
     var t = new Test 
     { 
      "hello", 
      { 5, 10 }, 
      { "whoops", 10, 20 } 
     }; 
    } 

    public void Add(string x) 
    { 
     Console.WriteLine("Add({0})", x); 
    } 

    public void Add(int x, int y) 
    { 
     Console.WriteLine("Add({0}, {1})", x, y); 
    } 

    public void Add(string a, int x, int y) 
    { 
     Console.WriteLine("Add({0}, {1}, {2})", a, x, y); 
    } 

    IEnumerator IEnumerable.GetEnumerator()   
    { 
     throw new NotSupportedException(); 
    } 
} 
+0

http://msdn.microsoft.com/en-us/ library/bb531208.aspx – pm100

+2

Hãy có một liên kết đến tài liệu MSDN trong câu trả lời, ít nhất. :) –

+0

@DanJ: Vâng, tôi đang đến đó :) –

7

Cú pháp khởi tạo bộ sưu tập đó. Đây:

RouteValueDictionary d = new RouteValueDictionary() 
{        //<-- A: what C# feature is this? 
    {"id",id},     //<-- B: what C# feature is this also?  
    {"saveChangesError",true} 
}); 

về cơ bản là tương đương với điều này:

RouteValueDictionary d = new RouteValueDictionary(); 
d.Add("id", id); 
d.Add("saveChangesError", true); 

Trình biên dịch nhận thực tế là nó thực hiện IEnumerable và có một phương pháp thích hợp Add và sử dụng đó.

Xem: http://msdn.microsoft.com/en-us/library/bb531208.aspx

+4

"cú pháp khởi tạo từ điển" làm cho âm thanh như C# * như một ngôn ngữ * có kiến ​​thức tích hợp từ điển. Nó không. Nó sẽ làm việc với * any * type thực hiện 'IEnumerable' và có các phương thức' Add' thích hợp. –

+1

@JonSkeet: Làm thế nào để nó nhận ra thực tế rằng đó là một 'KeyValuePair'? – Ryan

+3

@minitech: Không. Nó nhận ra thực tế rằng có một phương thức 'Add (key, value)'. Xem câu trả lời của tôi cho một ví dụ về điều này. Cũng lưu ý rằng trong thực tế, biến chỉ được gán * sau * các cuộc gọi 'Thêm' - nó giống như bạn đã có một biến tạm thời trước đó. –