2014-11-06 26 views
19

Điều gì đó khiến tôi ngạc nhiên khi nhìn vào động lực C# hôm nay (tôi chưa bao giờ sử dụng chúng nhiều, nhưng gần đây tôi đã thử nghiệm với khung web Nancy). Tôi thấy rằng tôi không thể làm điều này:Tại sao tôi không thể lập chỉ mục vào ExpandoObject?

dynamic expando = new ExpandoObject(); 

expando.name = "John"; 

Console.WriteLine(expando["name"]); 

Dòng cuối cùng ném một ngoại lệ:

Không thể áp dụng lập chỉ mục với [] để một biểu hiện của loại 'System.Dynamic.ExpandoObject'

Tôi hiểu thông báo lỗi, nhưng tôi không hiểu tại sao điều này xảy ra. Tôi đã xem tài liệu cho ExpandoObject và nó thực hiện một cách rõ ràng IDictionary<,> và do đó có phương thức this.[index] (MSDN). Tại sao tôi không thể gọi nó?

Tất nhiên, không có gì ngăn tôi từ chối chuyển từ ExpandoObject sang từ điển theo cách thủ công và sau đó lập chỉ mục vào từ điển, nhưng loại đó không tuân theo điểm; nó cũng không giải thích cách Expando có thể ẩn phương thức của một trong các giao diện của nó.

Điều gì đang xảy ra ở đây?

+3

triển khai giao diện rõ ràng chỉ có thể được truy cập nếu đối tượng được đúc vào giao diện đó, nó không phải là một cái gì đó đặc biệt để ExpanoObject. –

+1

mã nguồn liên quan: http://referencesource.microsoft.com/#System.Core/Microsoft/Scripting/Actions/ExpandoObject.cs,552 –

Trả lời

28

cách expando đã có thể ẩn các phương pháp của một trong các giao diện của nó.

Vì bạn đã tìm thấy chính xác trong tài liệu, indexer is một explicit interface implementation. Từ Explicit Interface Implementation Tutorial:

Lớp học triển khai giao diện có thể triển khai rõ ràng thành viên của giao diện đó. Khi một thành viên được triển khai một cách rõ ràng, nó không thể được truy cập thông qua một cá thể lớp, mà chỉ thông qua một cá thể của giao diện.

Điều này có nghĩa bạn sẽ phải bỏ tham chiếu đến giao diện để truy cập nó:

((IDictionary<String, Object>)expando)["name"] 
+0

Cảm ơn @CodeCaster. Tôi biết về thực hiện giao diện rõ ràng, nhưng tôi nghĩ rằng nó chỉ là để thực hiện hai thành viên có cùng tên; Tôi chưa bao giờ thấy nó được sử dụng chỉ để che giấu một thành viên trước đây. Bạn có biết tại sao họ đã làm điều này với ExpandoObject? – Richiban

+1

một @Richiban chỉ có thể đoán, nhưng xem [câu trả lời Marc Gravell về một câu hỏi tương tự] (http://stackoverflow.com/questions/280495/why-to-use-explicit-interface-implementation-to-invoke-a- protected-method): _ "để giữ cho API công cộng cốt lõi sạch" _. – CodeCaster

+7

Điều này dường như đánh bại mục đích của việc sử dụng ExpandoObject. Cũng có thể khai báo nó như một từ điển. – Triynko

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