Skip to content

Instantly share code, notes, and snippets.

@jeffora
Created September 27, 2011 01:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffora/1243959 to your computer and use it in GitHub Desktop.
Save jeffora/1243959 to your computer and use it in GitHub Desktop.
Massive dynamic issues
// Example 1:
// conn has a compile time type of DbConnection, as this is what is returned by OpenConnection
// cmd has compile time type of DbCommand, as this is what is returned by CreateCommand
// Both have runtime types of the more specific SqlConnection/SqlCommand
public static dynamic DynamicWeirdness() {
using (var conn = OpenConnection()) {
var cmd = CreateCommand("SELECT * FROM Products");
cmd.Connection = conn;
}
Console.WriteLine("It worked!");
Console.Read();
return null;
}
// Example 2:
// conn has a compile time type of DbConnection, as this is what is returned by OpenConnection
// cmd is only evaluated at runtime due to dynamic. At runtime, it becomes the most specific SqlCommand
// SqlCommand.Connection requires SqlConnection and although conn's runtime type is SqlConnection, its
// compile-time is still DbConnection and thus you get the error
public static dynamic DynamicWeirdness() {
dynamic ex = new ExpandoObject();
ex.TableName = "Products";
using (var conn = OpenConnection()) {
var cmd = CreateCommand(ex);
cmd.Connection = conn;
}
Console.WriteLine("It worked!");
Console.Read();
return null;
}
// Example 3:
// conn has a compile time type of DbConnection, as this is what is returned by OpenConnection
// cmd is evaluated at runtime due to dynamic to be any type compatible with DbCommand.
// Runtime type is still SqlCommand, but compile-time is specified as DbCommand (due to not using var).
// DbCommand.Connection accepts DbConnection, which is the compile-time type of conn
public static dynamic DynamicWeirdness() {
dynamic ex = new ExpandoObject ();
ex.Query = "SELECT * FROM Products";
using (var conn = OpenConnection()) {
DbCommand cmd = CreateCommand(ex); // <-- DON'T USE VAR
cmd.Connection = conn;
}
Console.WriteLine("It worked!");
Console.Read();
return null;
}
@robconery
Copy link

OK so the next twist is that if I set "using dynamic conn = OpenConnection()" it works as well. What I mean by "the entire block is an expression" means exactly that - if you hover over it the compiler has no idea what's going on - there's "too much dynamic" happening. So it hands it off to the runtime binder to figure out.

Now here's where it gets interesting. Take a look at the question again - see the last edit? See where I output the runtime types for each variable? They're SqlClient.

We're talking in circles here - but everything you're writing here is not convincing me that there's a compile-time type for the code I've written. There can't be. It's dynamic and maybe IL is taking a swing at figuring it out... but there's no way that you and I can know what that special magic is since we're not compilers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment