anon
anon

Reputation:

Why is linq 'First()' on dynamic type sometimes failing at runtime?

I have this strange behavior of linq at runtime in a c# .NET 4.6.1 project. I'm reusing a dynamic type to hold the result set coming from Dapper queries (not shown here).

Consider the following code:

...
IEnumerable<dynamic> resultSet = await dataSource.GetUserInfos(unlockingUserId, applicationName);
...

The incoming result set contains one row with many different columns.

Later in the code, I'm assigning the resultSet object with the result of another database query:

resultSet = await dataSource.ReleaseLock(userId, unlockingUserId, itemId, sessionId);

This time the row returned from the server still contains one row but only one boolean column named, say 'success'.

The following code:

...
if (resultSet.First().success != true)

fails with the following runtime exception:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.Collections.Generic.List' does not contain a definition for 'First'

I have no problem when using another dynamic object for holding the results:

IEnumerable<dynamic> unlocked = await dataSource.ReleaseLock(userId, unlockingUserId, itemId, sessionId);

This time, the following code:

...
if (unlocked.First().success != true)

Works fine.

EDIT : It was a mistake on my side. GetUserInfos was returning dynamic instead of IEnumerable.

Upvotes: 1

Views: 760

Answers (1)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131374

Enumerable.First() is an extension method defined in Enumerable, not a method of List. In reality, they are static methods that are made to look like instance methods through compiler magic. The compiler knows to translate extension method calls to their static equivalent, ie Enumerable.First() becomes Enumerable.First(someEnumerable,...).

When you call First() dynamically though, it is called as a method on the dynamic object. The runtime searches the dynamic methods of the object and can't know that you wanted to call some static method instead.

You may be able to use extension methods if you call them in their static form directly, ie if (!Enumerable.First(unlocked)) ...

Upvotes: 2

Related Questions