Created
September 27, 2011 01:02
-
-
Save jeffora/1243959 to your computer and use it in GitHub Desktop.
Massive dynamic issues
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.