Fun with C#: Before there were dynamic features

In my previous post, I mentioned about Visual FoxPro being a weakly-typed, dynamic, object-oriented language, which also featured it’s own SQL (Structured Query Language), and a fast local database. When I got to C#, I found a language that was strongly-typed, object-oriented, with no easy way to perform queries, and very hard to create dynamic behavior. But let me brake that down, pretty much the way I did with FoxPro in the previous post:

Object-Oriented

Instantiate an object and call a method on it. Similar to the way I did in FoxPro, but with a key difference: the class name isn’t a string passed into a function!

User user = new User();
user.SayHello();

SQL (Structured Query Language)?

In the first two versions of C# there was just no easy way to query things. But then we were presented with LINQ (Language Integrated Query) in version 3!!

myCustomers = from c in customers 
                           where c.Id == 1 
                           select c;

customer = myCustomers.SingleOrDefault();

customer.Address 
customer.PhoneNumber 

That was very similar to the way I could do a SELECT followed by a SCATTER in FoxPro. I loved it!

I didn’t like the way the code read, though, with the “select” coming at the end (after so many years of starting my queries with SELECT). Once I got over that, I started to appreciate the fact that I could write my queries like this:

customer = customers.where(c => c.Id == 1).SingleOrDefault();

Or even better, like this:

Customer customer = customers.SingleOrDefault(c => c.Id == 1);

“What does that have to do with the topic of this series?”, you might ask. Stay with me…

Strongly-typed

Consider the following code:

var myVariable = 1234;
myVariable = “Woohoo!!”;   // Nope...

Well, since C# is strongly-typed, knowing the type of data we get back from queries is very important. Take this example:

var customers = customers 
                 .SingleOrDefault(c => c.Id == 1)
                 .Select(c => new { Address = c.Address, PhoneNumber = c.PhoneNumber  });

When C# 3 introduced type inference, many developers were confused with the keyword var, thinking it meant “variant”; in other words, a variable declared as var should be assigned different types of data at will. That was not the case; var was just a way to tell the compiler “hey, the type of this variable will be whatever type I’m assigning to it as I declare it.”

With that said, in prior examples we were having the query return a Customer object. In the example above, on the other hand, we return some sort of list of anonynous objects, by using the new keyword without the name of a class, but giving it the properties and initial values we want on them. So we just told the compiler “I need a new object that has these properties with these values”. The compiler creates a class for us containing those properties; it is not a class created dynamically during runtime.

Now, let’s take that example a step further:

var customers = customers 
                  .SingleOrDefault(c => c.Id == 1)
                  .Select(c => new { c.Address, c.PhoneNumber  });

customers = “can’t do this!”;

Again, we declare a customers variable, and let the compiler infer its type. Next, we try to assign some string content to that same variable. The compiler yells at us, proving that var does not mean variant.

Dynamic (before C# Dynamic)

Let’s now have a look at how we implement dynamic things before the so-called “C# Dynamics” were introduced. Let’s revisit this simple sample:

User user = new User();
string hello = user.SayHello();
Console.WriteLine(hello);

What if we didn’t know during compile time what type of User to instantiate? And what if we only knew during runtime what method to execute? The way to that back then was only by using .NET Reflection, like so:

var instanceType = Type.GetType("Playground.User");            
object instance = Activator.CreateInstance(instanceType);            

MethodInfo theMethod = instanceType.GetMethods().SingleOrDefault(m => m.Name == "SayHello");           
object hello = theMethod.Invoke(instance, null); 
           
Console.WriteLine(hello.ToString());

That way, both the class and method names where represent by strings. When doing that, we always work with object; that’s what the Activator’s CreateInstance method returns, and it’s also what the Invoke method on a MethodInfo instance returns. Using type inference here (declaring the variables with var) wouldn’t help us much.

Another option to create some sort of dynamic code back then was by emitting IL (Intermediate Language). Not exactly a fun thing to do. There are good cases for it, though, so check out some real world users of Reflection.Emit.

Yet another option, which I’ve used at least twice in successful projects, was to build C# code as strings within the application, and handle it over to the C# compiler during runtime. What type of code got created dynamically was controlled within the application, and it was executed within a sandbox, so the end-users couldn’t really “do anything they wanted”. In fact, I have used this approach in conjunction with the dynamic features once they become available.

Coming up next, dynamic code after the C# dynamic features arrived. Stay tuned!

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: