2008-11-24 11 views
22

Có điều gì để sử dụng không, để xác định xem một loại có thực sự là một loại ẩn danh không? Ví dụ một giao diện, vv?Các loại ẩn danh - Có bất kỳ đặc điểm phân biệt nào không?

Mục đích là để tạo ra một cái gì đó như sau ...

//defined like... 
public static T Get<T>(this IAnonymous obj, string prop) { 
    return (T)obj.GetType().GetProperty(prop).GetValue(obj, null); 
} 
//... 

//And then used like... 
var something = new { name = "John", age = 25 }; 
int age = something.Get<int>("age"); 

Hoặc là chỉ là vẻ đẹp của một loại vô danh? Không có gì để xác định nó bởi vì nó có hình dạng mới?

Note - Tôi nhận ra rằng bạn có thể viết một phương pháp mở rộng cho các đối tượng lớp , nhưng điều đó có vẻ như một overkill chút, theo ý kiến ​​của tôi.

Trả lời

48

EDIT: Danh sách bên dưới áp dụng cho các loại ẩn danh C#. VB.NET có các quy tắc khác nhau - đặc biệt, nó có thể tạo ra các loại vô danh có thể thay đổi (và làm theo mặc định). Jared đã chỉ ra trong bình luận rằng phong cách đặt tên là khác nhau, quá. Về cơ bản đây là tất cả khá mong manh ...

Bạn không có thể xác định nó trong một hạn chế chung, nhưng:

  • Nó sẽ là một lớp (chứ không phải giao diện, enum, struct vv)
  • nó sẽ có CompilerGeneratedAttribute áp dụng cho nó
  • nó sẽ ghi đè Equals, GetHashCode và ToString
  • nó sẽ nằm trong không gian tên toàn cầu
  • nó sẽ không được lồng trong một loại
  • Đó sẽ là nội
  • Nó sẽ được niêm phong
  • Nó sẽ lấy trực tiếp từ object
  • Sẽ chung với bao nhiêu tham số kiểu như tài sản. (Bạn có thể có loại ẩn danh không chung chung, không có thuộc tính.)
  • Mỗi thuộc tính sẽ có thông số loại có tên bao gồm tên thuộc tính và sẽ có thông số loại đó, ví dụ: Tên bất động sản trở thành một loại tài sản của <> _name
  • Mỗi thuộc tính sẽ được công khai và readonly
  • Đối với mỗi tài sản sẽ có một tương ứng với lĩnh vực readonly tin
  • Sẽ không có tài sản hoặc các lĩnh vực
  • khác
  • Sẽ có một hàm khởi tạo lấy một tham số tương ứng với từng tham số kiểu, theo thứ tự như các tham số kiểu
  • Mỗi phương pháp và thuộc tính sẽ áp dụng DebuggerHiddenAttribute áp dụng cho nó.
  • Tên của loại sẽ bắt đầu với "<>" và chứa "AnonymousType"

Rất ít trong số này được đảm bảo bởi các đặc điểm kỹ thuật, tuy nhiên - vì vậy nó có thể tất cả các thay đổi trong phiên bản tiếp theo của trình biên dịch hoặc nếu bạn sử dụng Mono, v.v.

+7

Tiền tố tên <> chỉ là C#. Trong VB tiền tố tên sẽ là "VB $ AnonymousType" – JaredPar

+1

Ooh, đó là giá trị biết. Tôi dám nói rằng một vài thứ khác cũng chỉ áp dụng cho C# - đặc biệt là những thứ VB có thể thay đổi được. Sẽ chỉnh sửa để phản ánh điều đó. –

+0

Tôi đã quét phần còn lại của các mục nhập và chỉ có hai lỗi VB khác. Các trường không có tiền tố <> _ name. Ngoài ra phiên bản VB có thêm một tài sản riêng được gọi là AtDebuggerDisplay được sử dụng cho các lý do hiệu suất trong khi gỡ lỗi – JaredPar

4

Như tôi nhớ lại, có một điểm đánh dấu [CompilerGenerated] ... 2 giây

Thêm tên sẽ được freaky, và nó sẽ là một kiểu generic ;-p

Trên thực tế, đối với một "nhận được" vv Tôi có lẽ sẽ chỉ sử dụng một phương pháp tĩnh (không mở rộng).

Nếu bạn chỉ muốn có một cách để lấy giá trị từ một thể loại anon (tại thời điểm sau), lambda có lẽ là lựa chọn tốt nhất - lưu ý rằng bạn cần một vài thủ thuật để gỡ bỏ:

static void Main() 
    { 
     var foo = new { name = "John", age = 25 }; 
     var func = Get(foo, x => x.age); 
     var bar = new { name = "Marc", age = 30 }; 
     int age = func(bar); 
    } 
    // template here is just for type inference... 
    static Func<TSource, TValue> Get<TSource, TValue>(
     TSource template, Func<TSource, TValue> lambda) 
    { 
     return lambda; 
    } 

(chỉnh sửa lại những nhận xét) có chắc chắn thuộc tính này:

 var foo = new { A = "B" }; 
     Type type = foo.GetType(); 

     CompilerGeneratedAttribute attrib = (CompilerGeneratedAttribute) Attribute.GetCustomAttribute(
      type, typeof(CompilerGeneratedAttribute)); // non-null, therefore is compiler-generated 
+0

Không, thuộc tính được tạo bởi trình biên dịch – JaredPar

+0

@JaredPar: Chắc chắn là trong thử nghiệm nhỏ của tôi. –

+1

[CompilerGenerated] distiguishes một vũ trụ lớn hơn nhiều mà các loại vô danh. – JaredPar

1

Theo mục đích của phương pháp khuyến nông không có cách nào để phân biệt một loại vô danh. Các phương thức mở rộng hoạt động bằng cách xác định một phương thức cho một kiểu thời gian biên dịch có thể đặt tên. Các loại ẩn danh không được đặt tên và do đó không thể nhìn thấy tại thời gian biên dịch. Điều này làm cho chúng không tương thích với các phương pháp mở rộng.

+0

Vâng, bạn không thể thực hiện quá tải cụ thể hơn cho một loại ẩn danh - tuy nhiên, các phương pháp mở rộng (nói chung) theo một số cách tại * hữu ích nhất * của chúng với các loại ẩn danh. –

+0

Bằng cách nào? Không có cách nào để truy cập tĩnh một thành viên của một kiểu vô danh thông qua một phương thức mở rộng chung. Bạn có thể sử dụng một hack vinh quang trong một phương pháp mở rộng không chung chung nhưng nó liên quan đến việc tạo ra một loại không được sử dụng, đúc và nhận được giá trị – JaredPar

+0

Thực tế bạn có thể - thông qua một lambda vv Nhưng một phương pháp mở rộng chung trên (ví dụ) IEnumerable vv là cơ chế chính để truyền một loại anon mạnh mẽ (T) ra khỏi một phương thức và làm việc với nó theo cách hữu ích (thông qua Func , Hành động , v.v.). –