Passing dynamic object to C# method changes return type

This is because almost any operation involving a dynamic value is resolved dynamically at execution time. There are no exceptions made for cases where actually there’s only one method present at compile-time; the language is simpler that way. (For certain calls, the compiler does perform enough resolution at compile-time to ensure that there is at least one method with a suitable number of parameters – this is specified in the C# 5 spec in section 7.5.4, but that doesn’t affect the effective return type.)

From the C# 5 spec, section 7.6.5:

An invocation-expression is dynamically bound if at least one of the following holds:

  • The primary-expression has compile-time type dynamic.
  • At least one argument of the optional argument-list has compile-time type dynamic and the primary-expression does not have a delegate type.

In this case the compiler classifies the invocation-expression as a value of type dynamic. […]

There are a few operations involving dynamic values which still have a non-dynamic overall type. For example:

  • d is Foo is always bool
  • d as Foo is always Foo
  • new Foo(d) is always Foo even though the exact constructor to use is determined at execution time

But any method call is treated as having a return type of dynamic.

Leave a Comment