2013-01-01 39 views
10

tôi đã viết phương pháp mở rộng này:Chuyển đổi thành IEnumerable <dynamic>?

public static class A 
{ 
public static IEnumerable<dynamic> AsDynamic<T>(this IEnumerable<T> f) 
    { 
     foreach (var element in f) 
     { 
       yield return (dynamic) element; 
     } 
    } 
} 

Và thử nghiệm nó:

List<int> l = new List<int>(){1,2,3}; 
Console.WriteLine (l.AsDynamic().GetType()); 

Tuy nhiên sản lượng là: typeof (IEnumerable<Object>)

  • Tại sao nó không phải là typeof (IEnumerable<dynamic>)?

  • Làm cách nào để làm cho nó giống như vậy?

+2

["Trong hầu hết các trường hợp, nó hoạt động giống như nó có đối tượng kiểu."] (Http://msdn.microsoft.com/en-us/library/dd264736.aspx) –

+1

Không có loại 'động' khi chạy , chúng chỉ được nhập là đối tượng và thông tin liên kết phương thức là đầu ra tại mỗi trang cuộc gọi liên quan đến một biến động. – Lee

Trả lời

21

Tôi nghĩ rằng bạn hiểu sai về ý nghĩa của dynamic. Về cơ bản, khi bạn nói với trình biên dịch rằng kiểu của đối tượng là dynamic, bạn "hứa" rằng đối tượng khi chạy sẽ hỗ trợ bất kỳ phương thức hoặc thuộc tính nào mà bạn gọi, để đổi lấy trình biên dịch không phàn nàn tại thời gian biên dịch. Bạn cũng hứa rằng bạn sẽ phải đối mặt với những hậu quả nếu bạn phá vỡ lời hứa của bạn.

Khi bạn nói rằng một đối tượng là dynamic, trình biên dịch không thể đưa ra các giả định về loại, vì vậy nó sử dụng object, biết rằng bất cứ điều gì có thể được lưu trữ là object. Khi bạn thực hiện một IEnumerable<dynamic>, nó trở nên IEnumerable<object>, với một sự khác biệt đáng kể: bạn có thể gọi bất kỳ phương pháp trên các yếu tố của nó, và trình biên dịch sẽ không nói một lời:

IEnumerable<SomeType> original = ... 
foreach (dynamic x in original.AsDynamic()) { // Using your method 
    Console.WriteLine(x.SomeUnsupportedMethod()); // The compiler is silent! 
} 

Kể từ original.AsDynamic() đưa ra một chuỗi các dynamic đối tượng, các trình biên dịch không phàn nàn về cuộc gọi của bạn tới SomeUnsupportedMethod.Nếu phương pháp này thực sự không được hỗ trợ trong thời gian chạy, chương trình sẽ sụp đổ; nếu phương thức này thực sự được hỗ trợ bởi các phần tử của SomeType, sẽ không có sự cố và phương thức sẽ được gọi.

Đó là tất cả các dynamic sẽ làm cho bạn; tĩnh, "trình giữ chỗ" sẽ giữ nguyên là objecttypeof sẽ cho bạn biết nhiều. Nhưng các khả năng chính xác của đối tượng (các phương thức và thuộc tính của nó) sẽ không được kiểm tra cho đến khi chạy.

+1

Như tôi đã hiểu từ các cuộc thảo luận trong các bình luận cho một câu trả lời khác, viết 'typeof (IEnumerable )' thực sự là hợp pháp (nhưng không hữu ích!) Trong C#, nhưng nó tạo ra cùng kiểu thời gian chạy như 'typeof (IEnumerable )'. Tuy nhiên, 'typeof (dynamic)' không được cho phép như một từ đồng nghĩa cho 'typeof (object)'. Nhân tiện, 'GetType()' sẽ không bao giờ trả về một kiểu giao diện, tất nhiên, vì vậy Poster gốc không chính xác. –

+0

@JeppeStigNielsen http://i.stack.imgur.com/9C4sD.jpg –

+0

@RoyiNamir Tôi không chắc chắn tôi hiểu ảnh chụp màn hình của bạn (Tôi không quen với LINQPad). Hai dòng có kiểu chữ khác nhau. Chúng không phải là đầu ra của hai cuộc gọi phương thức 'WriteLine'. 'GetType()' trả về một đối tượng 'RuntimeType', trong phương thức' WriteLine' đầu tiên 'ToString()' được gọi trên nó. Loại sẽ là một loại được tạo ra (lớp có tên lạ với các ký tự '<', '>' và '__' trong đó) vì bạn có một khối lặp (' lợi nhuận'). Hãy thử điều này: 'if (l.AsDynamic(). GetType() == typeof (IEnumerable )) ném ngoại lệ mới (" Jeppe đã sai! ");' –

0

Thử phương pháp mở rộng LINQ Cast(). Nhưng tôi không chắc chắn nó sẽ làm việc với năng động.

0

dynamic không phải là một loại

Console.WriteLine(typeof(dynamic)); // error 

động chỉ giải quyết các loại thực tế tại thời gian chạy

+0

MSDN cũng đề cập đến "loại": [Visual C# 2010 giới thiệu một loại mới, năng động] (http://msdn.microsoft.com/en-us/library/dd264736.aspx) –

+0

@ Some1.Kill.The. DJ - Cố gắng sử dụng kết quả 'typeof (động)' trong một lỗi biên dịch, "Toán tử typeof không thể được sử dụng trên kiểu động." – Lee

+0

@Lee 'dynamic' là một loại không được biết đến tại thời gian chạy..động và đối tượng là tương tự, ngoại trừ động cho phép bạn làm những việc không thể thực hiện tại thời gian biên dịch – Anirudha

1

Theo thiết kế, runtime bindings cư xử như tương tự càng tốt để tĩnh ràng buộc.

Vì vậy, các loại thời gian chạy sẽ typeof (IEnumerable<Object>)

Loại tĩnh sẽ typeof (IEnumerable<dynamic>)

Cũng

Các xử lý thời gian chạy đúng này khái niệm

typeof(object)==typeof(dynamic) 

Vì vậy,

Một năng động ty pe giống như đối tượng ngoại trừ nó cho phép bạn sử dụng theo những cách không được biết đến trong thời gian biên dịch.

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