2013-04-24 10 views
16

Tại sao tôi không thể truyền List<AnonymousObject> đến List<dynamic>? Tôi có mã sau đây:Cast Danh sách loại Ẩn danh vào Danh sách các đối tượng động

var datasource = someList.Select(o => new { x = o.A, y = o.B }); 
dgvSomeGridView.DataSource = datasource.ToList(); 
dgvSomeGridView.DataBind(); 

Sau đó, tôi truy cập vào GridView.DataSource với đoạn mã sau:

var ds = ((List<dynamic>)dgvSomeGridView.DataSource); 
.... 

Nhưng nó ném một lỗi trên dòng nơi tôi bỏ nó vào List<dynamic>, nó nói:

Không thể truyền đối tượng thuộc loại System.Collections.Generic.List'1[<>f__AnonymousType0'8[System.Int32,System.String]] để nhập System.Collections.Generic.List'1[System.Object].

Tại sao tôi không thể truyền danh sách loại ẩn danh tới một số dynamic hoặc do lỗi nói đến loại object? Làm cách nào tôi có thể giải quyết vấn đề này?

Mã của tôi nằm trong C#, framework 4.0, xây dựng trong VS2010 Pro, nền tảng là ASP.NET.

Xin vui lòng trợ giúp, cảm ơn trước.

Trả lời

35

Kể từ List<T> là trong biến thể, không đồng biến, vì vậy bạn phải đúc vào IEnumerable<dynamic> mà hỗ trợ đồng biến:

var ds = ((IEnumerable<dynamic>)dgvSomeGridView.DataSource).ToList(); 

Để biết thêm information about covariant

+1

đừng quên thêm ' sử dụng System.Linq; ' trong tiêu đề tài liệu của bạn trong trường hợp bạn chưa –

6

Thứ nhất, Đúc với generic không hoạt động theo cách đó. Dàn diễn viên này không hợp lệ:

List<string> source = GetStrings(); 
List<object> source2 = (List<object>) source; 

Lý do là Danh sách không phải là biến thể. Nếu có, bạn có thể source2.Add(source2); và đột nhiên source1 chứa chính nó khi nó chỉ nên có chuỗi.

Thứ hai, Anonymous types chỉ là các lớp được khai báo trình biên dịch có thuộc tính chỉ đọc và ngữ nghĩa bình đẳng giá trị. Nếu bạn đã tạo một lớp với thuộc tính chỉ đọc và ngữ nghĩa bình đẳng giá trị, lớp của bạn sẽ giống như một loại ẩn danh, ngoại trừ loại của bạn sẽ có tên được xác định của nhà phát triển, trong khi loại ẩn danh có tên được xác định là trình biên dịch. Các loại Anon không đặc biệt.

Thứ ba, dynamic biến là cách để kiểm tra loại trình biên dịch. Họ không đi xung quanh kiểm tra kiểu thời gian chạy. Bạn có thể sử dụng cú pháp C# casting để chuyển đổi rõ ràng kiểu thành dynamic ... lưu ý: đây không phải là một diễn viên! Bạn không thể thực hiện một phép đúc thời gian chạy tới một kiểu không tồn tại trong thời gian chạy.

Tuy nhiên, các hoạt động chứa các biểu thức thuộc loại động không được giải quyết hoặc loại được trình biên dịch kiểm tra. Trình biên dịch gộp các thông tin về hoạt động và thông tin đó sau đó được sử dụng để đánh giá hoạt động tại thời gian chạy. Là một phần của quá trình, các biến của kiểu động được biên dịch thành các biến của đối tượng kiểu. Do đó, nhập động chỉ tồn tại ở thời gian biên dịch, không phải lúc chạy.

static void convertToDynamic() 
{ 
    dynamic d; 
    int i = 20; 
    d = (dynamic)i; 
    Console.WriteLine(d); 

    string s = "Example string."; 
    d = (dynamic)s; 
    Console.WriteLine(d); 

    DateTime dt = DateTime.Today; 
    d = (dynamic)dt; 
    Console.WriteLine(d); 

} 
// Results: 
// 20 
// Example string. 
// 2/17/2009 9:12:00 AM 

Cuối cùng, nếu bạn vẫn muốn có một List<dynamic>, làm điều này:

var anonList = GetAnonList(); 
List<dynamic> dynamicList = anonList.Select(x => (dynamic)x).ToList(); 

Nhưng bạn có thể cũng giống như dễ dàng làm được điều này:

var anonList = GetAnonList(); 
List<object> objectList = anonList.Cast<object>().ToList(); 
+0

Tuyệt vời, điều này phù hợp với tôi! –