Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What causes "extension methods cannot be dynamically dispatched" here?

Compile Error

'System.Data.SqlClient.SqlConnection' has no applicable method named 'Query' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.

Now, I know how to work around the problem, but I'm trying to get a better understanding of the error itself. I have class that I'm building to leverage Dapper. In the end I'm going to provide some more custom functionality to make our type of data access a lot more streamlined. In particular building in tracing and stuff. However, right now it's as simple as this:

public class Connection : IDisposable {     private SqlConnection _connection;      public Connection()     {         var connectionString = Convert.ToString(ConfigurationManager.ConnectionStrings["ConnectionString"]);         _connection = new SqlConnection(connectionString);         _connection.Open();     }      public void Dispose()     {         _connection.Close();         _connection.Dispose();     }      public IEnumerable<dynamic> Query(string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)     {         // this one works fine, without compile error, so I understand how to         // workaround the error         return Dapper.SqlMapper.Query(_connection, sql, param, transaction, buffered, commandTimeout, commandType);     }      public IEnumerable<T> Query<T>(string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)     {         // this one is failing with the error         return (IEnumerable<T>)_connection.Query(sql, param, transaction, buffered, commandTimeout, commandType);     } } 

but interestingly enough, if I were to simply issue a statement like this:

_connection.Query("SELECT * FROM SomeTable"); 

it compiles just fine.

So, can somebody please help me understand why leveraging the same overload inside of those other methods is failing with that error?

like image 338
Mike Perrenoud Avatar asked Mar 13 '13 16:03

Mike Perrenoud


People also ask

Why extension methods are static?

Extension methods are static because they get the instance passed in via the first parameter, and they don't act on the actual instance of their declaring class. Also, they're just a syntactic sugar. CLR doesn't support such a thing.

Do extension methods have to be static?

An extension method must be a static method. An extension method must be inside a static class -- the class can have any name. The parameter in an extension method should always have the "this" keyword preceding the type on which the method needs to be called.

Can we call a method from an extension on dynamic types?

We can not call the Extension method on the dynamic type.

What is the difference between a static method and an extension method?

The only difference between a regular static method and an extension method is that the first parameter of the extension method specifies the type that it is going to operator on, preceded by the this keyword.


1 Answers

So, can somebody please help me understand why leveraging the same overload inside of those other methods is failing with that error?

Precisely because you're using a dynamic value (param) as one of the arguments. That means it will use dynamic dispatch... but dynamic dispatch isn't supported for extension methods.

The solution is simple though: just call the static method directly:

return SqlMapper.Query(_connection, sql, param, transaction,                        buffered, commandTimeout, commandType); 

(That's assuming you really need param to be of type dynamic, of course... as noted in comments, you may well be fine to just change it to object.)

like image 59
Jon Skeet Avatar answered Oct 01 '22 08:10

Jon Skeet