Thursday, October 29, 2009

Scary Halloween-Style C# 4.0 Code

Check out the following code:

using System;
using System.Dynamic;

namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
d.Hola = "Howdy";
SaySomething(d);
}

void SaySomething(dynamic d)
{
Console.WriteLine(d.Hola);
}
}
}

What do you think this code should do? There's no static method to accept the incoming parameter, so compile error, right?

Wrong.

This compiles, but blows up at runtime with a RuntimeBinderException, not finding the instance method SaySomething.



While the above compiles just fine, the following does not:

using System;
using System.Dynamic;

namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
d.Hola = "Howdy";
SaySomething(d);
}
}
}

Rightly recognizing that SaySomething doesn't exist in the current context.

This is the scariest thing I've seen all week. And I was in Austin last weekend.

So why does it do this? This goes back to the way that overload resolution is achieved during compilation. Eric Lippert wrote about this problem in C# 3.0 earlier this year. Overload resolution steps (for C# 3.0) are as follows, in this order:

1. First, each overload is examined according to it's arguments.
2. Next the determination of whether or not the overload is accessible from the current static or instance context is made.
3. If the overload selected from step 1 is inaccessible, then a compile-time error is thrown.

Now, let's look at the situation I posed above. The major difference here is when this resolution occurs. The first example actually compiles, because the overload resolution is delayed until runtime. The order of operations, however, stays the same.

At runtime, these steps are performed in the following order:

1. First, each overload is examined according to it's arguments.
2. Next the determination of whether or not the overload is accessible from the current static or instance context is made.
3. If the overload selected from step 1 is inaccessible, then a run-time error is thrown.

In other words, the rules are exactly the same as they were in C# 3.0, but the consequences of this mistake while using dynamic are much more severe than they are when not using the dynamic type.

All this to say, the dynamic type is a nice addition to the C# toolbox, but it needs to be used with extreme care.

With great power comes great responsibility.

Monday, October 26, 2009

A Better Developer

We developers are constantly barraged with an overflow of activities and information we don't possibly have enough time for, and we're given very little guidance on what is and isn't worthwhile. This morning on my drive to work, I was reflecting on some of the things I'm involved with, questioning the usefulness of each. Some of these activities (other than the act of coding itself) include:
  • Using Twitter
  • Attending User Groups
  • Leading User Groups
  • Attending Conferences
  • Speaking at Conferences
  • Reading Books (of various kinds)
  • Writing Books
  • Participating in IRC
  • Contributing to Open-Source Projects
  • Taking Certification Tests
  • Contributing to Forums
  • Writing Blogs
  • Reading Blogs
  • LinkedIn
And that's just to name a few.

Which ones are and aren't worthwhile to you is wholly dependent on your personality, affinity, and general life direction.

There's a peer-pressure that comes with this (or any) industry to be noticed, but ultimately, the question we, as developers, should all be asking is "does this make me a better developer?" Answer that question, and you'll know what's worth giving your time to.

Wednesday, October 21, 2009

Adventures in Office Interop and C# 4.0

I had a chance earlier to play with the new features introduced to C# 4.0 for the support of Office Interop. There are a couple of notable features.

First, Type.Missing is no longer required to pass into COM calls. This means no more:

wbs.Open(@"somefile.xlsx", missing, missing, missing, 
missing, missing, missing,
missing, missing, missing,
missing, missing, missing,
missing, missing);

Instead you can opt for:

wbs.Open(@"somefile.xlsx");

Readability FTW!

Other changes include the ability to use the indexed methods ("get_Range" for example) using indexers. Now, instead of:

Range range = ws.get_Range("A1", "A1");

You can use:

Range range = ws.Range["A1"];

Combined with the optional parameters, this makes for another win for readability.

In some situations, this "inferred property" addition makes things even more readable. How many times when setting a value in Excel Interop have you done this:

range.set_Value(XlRangeValueDataType.xlRangeValueDefault, i);

Yeah, not too pretty. Try this on instead:

range.Value = i;

Uh-huh. Yep. Much, much more readable.

That is all.

Monday, October 19, 2009

Be a Better Polyglot with F#'s CompiledNameAttribute

F# introduces the CompiledNameAttribute with the October 2009 CTP. This attribute provides a way to specify the compiled name of a method or type written in F#. The big advantage here is the ability to prevent having to compromise on your naming schemes in either F# or any other language. Internally to the assembly, you can still use the names you give to the constructs when you define the construct. Externally, however, the name will be compiled into a ".NET Friendly" name, which you can specify using the CompiledNameAttribute.

Take, for example, the extension method I wrote in my previous post. Using the CompiledNameAttribute, I can refer to this in F# using one name, and in C# using another name.

[<System.Runtime.CompilerServices.ExtensionAttribute>]
module public Morton.Extensions.EnumerableExtensions
[<Microsoft.FSharp.Core.CompiledNameAttribute("OutputAll")>]
[<System.Runtime.CompilerServices.ExtensionAttribute>]
let internalNameGoesHereForOutputting (_this:System.Collections.Generic.IEnumerable<'T>) =
for x in _this do System.Console.WriteLine x |> ignore


Note the internal name here is "internalNameGoesHereForOutputting" while the external name will be "OutputAll".

This is a very nice feature indeed, and I'd love to see it implemented in other languages as well. Kudos to Don Syme and the rest of the F# team for this one. This is an excellent step towards polyglot programming: translation.

Writing Extension Methods in F# to Use in C#

F#, in my mind, is the language of implementation. It provides a concise syntax when writing code "in the small" that is in many ways superior to C#. This makes F# the ideal language for writing extension methods and other methods that perform operations that are frequently repeated.

Here's a small example on how to write an extension method in F# that takes a generic IEnumerable<T> and outputs each value to the console:

[<System.Runtime.CompilerServices.ExtensionAttribute>]
module public Morton.Extensions.EnumerableExtensions
[<System.Runtime.CompilerServices.ExtensionAttribute>]
let OutputAll (_this:System.Collections.Generic.IEnumerable<'T>) =
for x in _this do System.Console.WriteLine x |> ignore

Note the use of the ExtensionAttribute on both the module declaration and on the function declaration. Both of these are necessary to create the extension method.

In C#, this code could be called just like any other Extension method. First, add the proper using statements to your code, then call the method from any applicable type.

The following code compiles and works properly when referencing an F# assembly containing the above function:

using System.Collections.Generic;
using Morton.Extensions;

namespace ConsoleApplication1
{
static class Program
{
static void Main(string[] args)
{
List<string> list = new List<string>();
list.Add("David");
list.Add("Jennifer");
list.OutputAll();
}
}
}


Now we're cooking. I could see myself using F# for tons of utility methods where writing it in C# would simply be too cumbersome.

UPDATE (10/30/2009)

I received a question today asking how these extensions could also be used from F# as well, with the same syntax. It's not too difficult, but it does require a tiny bit of additional work. The final code would look something like this:

[<System.Runtime.CompilerServices.ExtensionAttribute>]
module public Morton.Extensions.EnumerableExtensions
[<System.Runtime.CompilerServices.ExtensionAttribute>]
let OutputAll (_this:System.Collections.Generic.IEnumerable<'T>) =
for x in _this do System.Console.WriteLine x |> ignore

type System.Collections.Generic.IEnumerable<'T> with
member this.OutputAll() = this |> OutputAll

Monday, October 12, 2009

On Teachability in Team Development

EDIT: Note that the terms "architect" and "developer" below are used loosely. This post deals most directly with the teachability of a specific team member, whether that team member is an architect, developer, tester, etc. This post assumes that the teacher, regardless of his role, is competent in teaching. The architect/developer dichotomy below is use purely as a convenience to the purpose of the post.

Software craftsmanship is more than just a set of intellectual know-how. Character traits also affect your ability to do the job. The biggest barrier I see to excellent programming is often a lack of teachability. It doesn't matter how smooth the software architecture is; if the developer can't or won't learn the architecture, it's of no use - the architecture will go by the wayside.

So in that vein, here are the top few barriers to teachability that I've seen:

Arrogance - The arrogant developer always has a better way, and his way is never wrong. He'll fail to be teachable, because he already believes he knows it all. According to him, his code is perfect, so he spends most of his time blaming others or outside factors for bugs that show up. He'll never implement an architecture properly, because the architecture, in his opinion, is not as good as he could have made it. Sadly, the arrogant developer was teachable at one point, but his success made him arrogant and he lost his ability to learn.

Laziness - A certain amount of laziness is a wonderful trait for a developer to have. It's this laziness that makes a developer say "There's gotta be a better way". Unbridled laziness, however, ignores the architecture "because it's too much work". It's not that he can't learn it, it's that he doesn't want to, and ugly code ensues.

Ability - Sadly, through no fault of their own, there are those developers that simply lack the ability to think logically, which is a needed trait for a developer. I don't believe that anyone can program, just as I don't believe that everyone can sell or perform scientific research or manage people. Different people have different strengths. Typically people who are not teachable in one thing are often teachable in another. These people should be encouraged to find those areas in which they excel. Luckily, these people are typically filtered out early on.

Apathy - This is related to laziness, but this developer isn't lazy - he's tired. He may be worn out on a particular project or with a particular technology, and he just doesn't care enough anymore to implement excellence.

In any of these situations, it's important to keep the team fresh. An infusion of new blood can often help to renew the team and make it into something vibrant again.

Friday, October 9, 2009

Closures in C#

LINQ has alot of "gotchas". Take the following code, for example:

using System;

namespace ConsoleApplication50
{
class Program
{
static void Main(string[] args)
{
int value = 100;
Action<int> curriedAction =
x => Console.WriteLine(x * value);
curriedAction(5);
}
}
}

How does C# handle closures? Let's take a closer look. Here's the IL for the Main method:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] class ConsoleApplication50.Program/<>c__DisplayClass1 CS$<>8__locals2)
L_0000: newobj instance void ConsoleApplication50.Program/<>c__DisplayClass1::.ctor()
L_0005: stloc.0
L_0006: ldloc.0
L_0007: ldc.i4.s 100
L_0009: stfld int32 ConsoleApplication50.Program/<>c__DisplayClass1::value
L_000e: ldloc.0
L_000f: ldftn instance void ConsoleApplication50.Program/<>c__DisplayClass1::<Main>b__0(int32)
L_0015: newobj instance void [mscorlib]System.Action`1<int32>::.ctor(object, native int)
L_001a: pop
L_001b: ldloc.0
L_001c: ldc.i4 200
L_0021: stfld int32 ConsoleApplication50.Program/<>c__DisplayClass1::value
L_0026: ret
}

Look at the locals declaration:
 .locals init (
[0] class ConsoleApplication50.Program/<>c__DisplayClass1 CS$<>8__locals2)

Looks like there's a whole lot more happening here than I originally intended. Instead of having a local integer variable, I'm spinning up a whole class simply to hold my single integer variable. In fact, there is no local integer variable in this method. It's this local <>c_DisplayClass1 instance that actually hosts the integer within it.

Also contained within this DisplayClass1 class is my delegate, which isn't just a static method at this point, it's an instance method.

public void <Main>b__0(int x)
{
Console.WriteLine((int) (x * this.value));
}

Interestingly, you can even view the variable for the target by calling the Target property of the curriedAction variable. If I add the following two lines to this method:

var target = curriedAction.Target;
Console.WriteLine(curriedAction.Target);
Console.WriteLine(target.GetType().GetField("value").GetValue(target));

I get this as part of the output:
ConsoleApplication50.Program+<>__DisplayClass1
100

So it appears that in situations where there is no closure, the compiler favors a static method, and in situations where there is a closure, the compiler favors an instance method on a compiler-generated class.

I've heard people complain about LINQ's performance versus a for or a foreach loop, and I wouldn't be surprised if this has something to do with it. Remember, each instantiated class will have to be collected at some point. All in all, I'd say to avoid using closures wherever possible whenever performance is an issue.

Thursday, October 8, 2009

User Interface Basics: Don't Taunt Your Users

The setup was taking a while so I moved on to other things. Which button do you think I wanted to press?

Wednesday, October 7, 2009

Covariance and the "ref" Keyword.

Here's a slight little detail worth noting.

If you're passing a value into a method that uses the "ref" keyword, the type of the variable passed must match the ref parameter exactly.

The value passed into the ref method is reassigned upon the method's completion, so the object reassigned must match the variable's declared type. If a variable's type is only derived from the parameter type requested by the method, there would be nothing stopping the method from reassigning the ref parameter internally thus causing a type mismatch on the method's completion.

Monday, October 5, 2009

On Blogging

I find my Google Reader queue fills up very quickly, and it's a rare situation in which I'm actually interested in reading most of the blogs I've added there. I find myself repeatedly attracted to the non-technical blogs, such as Seth Godin's blog. In all honesty, the technical blogs bore me after a while. I suppose my thought process goes something like this: "If I don't need to know about something right now, then why am I spending my time reading it?"

I think both are important, but I'm beginning to think that the technical blogs are good material for search engines, while the non-technical ones are the ones I really want to read on a daily basis. I only read the technical ones when I'm trying to figure out the details on exactly how to perform a task, while the non-technical ones really encourage me towards excellence in my craft.

I'm curious to know how many of you would say the majority of the blogs you follow are highly technical, and how many are less technical, but no less relevant, being applicable to more general aspects of your job.