Strange behavior of dynamic objects

I have a simple control method DoSomething which receives a json string, converts it to a dynamic object and tries to get the data:

[HttpPost]
public string DoSomething(string jsonStr)  // {"0":null,"1":"loadData"}
{
     // In this case obj.GetType() = System.Web.Helpers.DynamicJsonObject
     object obj = Json.Decode(jsonStr); 

     // Correct, a == "loadData"
     var a = (obj as dynamic)["1"];          

     // Incorrect, compilation exception:
     // "Cannot apply indexing with [] to an expression 
     // of type 'System.Web.Helpers.DynamicJsonObject'"
     var b = (obj as DynamicJsonObject)["1"] 

     return "OK"; 
}

My question is why it is possible to access an indexer when I use an object as a dynamic object at the time when the original type doesn't have an indexer?

Watches window

Jon Skeet
people
quotationmark

In the first case, you're using all the infrastructure of dynamic - which doesn't just use reflection to find "real" members, but also uses IDynamicMetaObjectProvider to provide support for members which are only known at execution time. This works because when you're using dynamic, the process of binding (working out what a member name means) is performed at execution time instead of at compile time.

In this case, it's the indexer which is being used at execution time - DynamicJsonObject doesn't declare an indexer, but overrides the TryGetIndex method of DynamicObject. The meta-object provider implementation of DynamicObject will route indexer "get" calls via TryGetIndex.

A simpler example of this is ExpandoObject:

ExpandoObject foo = new ExpandoObject();
// This is invalid; the compiler can't find a Property member
foo.Property = "broken";

dynamic bar = foo;
// This is fine; binding is performed at execution time.
bar.Property = "working";

people

See more on this question at Stackoverflow