2014-11-06 25 views
19

Qualcosa mi ha colto di sorpresa quando ho esaminato la dinamica C# (non li ho mai usati molto, ma ultimamente ho sperimentato con il framework web di Nancy). Ho scoperto che non potevo fare questo:Perché non posso indicizzare in un ExpandoObject?

dynamic expando = new ExpandoObject(); 

expando.name = "John"; 

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

L'ultima riga genera un'eccezione:

Impossibile applicare l'indicizzazione con [] per un'espressione di tipo 'System.Dynamic.ExpandoObject'

Ho capito il messaggio di errore, ma non capisco perché questo sta accadendo. Ho esaminato la documentazione di ExpandoObject e implementa esplicitamente IDictionary<,> e quindi ha un metodo this.[index] (MSDN). Perché non posso chiamarlo?

Naturalmente, non c'è niente che mi impedisca di downcasting il ExpandoObject a un dizionario manualmente e quindi l'indicizzazione in esso, ma questo tipo di sfida al punto; inoltre non spiega come Expando sia stato in grado di nascondere il metodo di una delle sue interfacce.

Cosa sta succedendo qui?

+3

implementazioni di interfacce esplicite sono accessibili solo se l'oggetto è gettato a tale interfaccia, non è qualcosa di particolare a ExpanoObject. –

+1

Codice sorgente pertinente: http://referencesource.microsoft.com/#System.Core/Microsoft/Scripting/Actions/ExpandoObject.cs,552 –

risposta

28

come Expando è stato in grado di nascondere il metodo di una delle sue interfacce.

Perché, come si correttamente scoperto nella documentazione, il indexer is un explicit interface implementation. Da Explicit Interface Implementation Tutorial:

Una classe che implementa un'interfaccia può implementare esplicitamente un membro di tale interfaccia. Quando un membro viene implementato esplicitamente, non è possibile accedervi tramite un'istanza di classe, ma solo attraverso un'istanza dell'interfaccia.

Questo significa che dovrete lanciare il riferimento all'interfaccia per accedervi:

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

Grazie a @CodeCaster. Sapevo dell'implementazione esplicita dell'interfaccia, ma pensavo che fosse solo per implementare due membri con lo stesso nome; Non l'avevo mai visto usato solo per nascondere un membro prima. Sai perché lo hanno fatto con ExpandoObject? – Richiban

+1

@Richiban si può solo intuire, ma si veda [la risposta di Marc Gravell su una domanda simile] (http://stackoverflow.com/questions/280495/why-to-use-explicit-interface-implementation-to-invoke-a- metodo protetto): _ "per mantenere pulita l'API pubblica principale" _. – CodeCaster

+7

Questo sembra vanificare lo scopo di utilizzare anche un ExpandoObject. Può anche solo dichiararlo come un dizionario. – Triynko

Problemi correlati