DCSIMG
March 2007 - Posts - Doron's .NET Space

March 2007 - Posts

Resharped

I am rather ashamed to admit that up until now I've never really tried to use Resharper, the very well known Visual Studio add-in. Today I decided to give Resharper 2.5 a try and was really blown away. Comparing Visual Studio 2005 without Resharper to Visual Studio 2005 with Resharper, is like comparing Turbo Pascal to, well, Visual Studio 2005. There's really no match here.

It starts with the little things, like how it always adds a matching brace to any brace you use ({,[,(). It makes you think why the hell isn't this already built in in Visual Studio. Or how the Resharped Intellisense always show the entire list of method overloads, without you having to scroll in the 7 method overloads or resort to MSDN.

But then you get to see the really smart stuff. Like the Refactoring features, which again make VS2005 attempt at this look rather silly. I'm talking about stuff like "Replace Constructor With Factory Method" or "Pull Members Up" (allows you to move a method implementation/declaration to a base class/interface), but also about simpler things such as "Safe Delete" (ever wanted to delete a class and wasn't sure what will break?) or "Convert Method To Property".

And imagine my amazement when I noticed this:

Which gets converted to...

And another extremely cool one:

 

And I haven't started to talk about the Live Templates, which are like Code Snippets only a lot smarter, or all the navigation features (especially the way it understands inheritance hierarchies), or about the way it marks redundant "using" directives in gray. It really is simply brilliant, and this is me talking after playing with it for about an hour.

Now the only question that remains is how to get the bosses to buy us those 250$ licenses...

Posted by dorony | with no comments

The trouble with Coverage of GAC Installed Assemblies

My team is starting to get into the whole unit-testing approach, and the first thing we're doing is adding unit-tests for the infrastructure assemblies. So I've written up some unit-tests, which I ran using NUnit and the wonderful TestDriven.NET Visual Studio tool, and the next thing I did was trying to test the coverage for said assembly, using NCover (again, by using TestDriven.NET's test with... coverage option).

When the results were opened in NCoverExplorer, I was very surprised to get no coverage results for the assembly I'm trying to test (the infrastructure one), I only got results for the testing assembly, which is of course rather pointless.

Reading a bit about how NCover works, I figured what the problem was. Being an infrastructure project, used by a few applications, the DLL got installed to the GAC in the post-build event of the project. Being in the GAC, NCover could not find the .pdb file it needs in order to provide coverage results. Hence, no coverage results.  And indeed, removing the assembly from the GAC did the trick and I got to see the results.

Only, I don't want to have to remove the assembly from the GAC, delete the post-build event and rebuild every time I want to test coverage. Surely, there is some way to tell NCover where to look for the pdb file? I mean, it does exist, it's just not copied to the test assembly's bin\debug directory.

Reading and asking around - I still haven't found a solution for this. Any ideas?

Posted by dorony | with no comments
תגים:,

My First C# 3.0 Program

I've finally decided to download the new "Orcas" CTP of Visual Studio, which includes support for the all new C# 3.0. Up until now I only read about it, so I thought it was about time I tried it myself. And it's awesome.

So, here's my "hello world" program.

public void MyFirstProgram(Func<string,string> doSomethingWithString)
{
var result
= doSomethingWithString("dlroW olleH");
Console.WriteLine(result);
}

public void Main()
{
MyFirstProgram(str
=> new string(str.Reverse().ToArray()));
}

This useless program demonstrates a few of the new C# 3.0 features.

The first thing you can notice about MyFirstProgram method, is the use of the "var" keyword. Is this javascript or C#? What's going on? Well, don't worry. C# has not gone all dynamically-typed on us. It's still very much statically typed, but it includes a new feature which allows us to specify local variables (and local variables only) without specifying their types. The compiler infers the type from by looking at the initializer for it. So this won't compile, since the compiler won't know how to infer the variable type:

var noInit;

Neither will this compile:

var x = 5;
x
= "5";

Remember, this is not javascript. Once the compiler has decided about the type of the local variable, it can't be changed again.

The second weird thing you've probably noticed is this weird syntax: "str => ...". This is actually an easier way to create an anonymous delegate. It's definitely easier than what you had to write in C# 2.0, which is...

delegate(string str)
{
return new string(str.Reverse().ToArray();
}

So str is the delegate parameter, but as you can see, we don't have to specify its type. The compiler infers the type of the parameter using the method to which we pass the delegate. In our case, it's this:

public void MyFirstProgram(Func<string,string> doSomethingWithString)

Func is a new built in generic delegate type, which has a few overloads. We're using the one in which we have one return value and one parameter, and our generic type is string. So, this method actually accepts a method, whose both return value and single parameter are strings. The cool thing is, that even though the "str => ..." does not specify the type of str, there is intellisense support for it in the new Visual Studio. So not only the compiler got a lot smarter in C# 3.0 - Visual Studio followed suit.

I really like the step the language has taken towards functional programming. The lambda expressions ("=>" syntax) really remind me of the Lisp variants of programming languages, and I can't wait to do more cool stuff with it. Still, the whole thing probably wouldn't have worked without great intellisense.

The next thing you might notice, is that String doesn't have a Reverse() method. You might think that in the new .NET Framework 3.5 the String class has changed, but as far as I can tell, it's exactly the same as in .NET 2.0. So where did this "Reverse" came from?

Well, another new feature of C# 3.0, and an integral part of the Linq project, is extension methods. This feature allows you to extend classes that you can't or don't want to inherit from. This includes built in .NET types as string, int, or in our case - the IEnumerable<T> interface. So Reverse is not a String method, what it really is, is an extension to the IEnumerable<T> interface. Since string implements IEnumerable<char>, it gets, "for free" a whole bunch of new methods which you can use. That means that if you're writing a collection, you don't have to inherit from some base-class to get lots of useful methods, if you only implement IEnumerable<T> you'll get methods like Reverse, Sum, Average, and many more.

To see how this works, let's "go to definition" on our reverse method. We'll see this:

namespace System.Linq
{

public static class Enumerable
{
......
public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source);
....
}
}

As you can see, we were sent to the static Enumerable class with a lots of static methods, which include parameters such as "this IEnumerable<TSource>". This is the syntax for creating an extension to a certain class.

Let's have a look at the Reflector to better understand what's going on (I actually had to go and use an older version of the Reflector to show you what's under. The new Reflector got all smart on me and displays the code almost identically as its C# origin).

1 [CompilerGenerated]
2 private static Func<string, string> <>9__CachedAnonymousMethodDelegate1;
3
4 public void MyFirstProgram(Func<string, string> doSomethingWithString)
5 {
6 string text1 = doSomethingWithString("dlroW olleH");
7 Console.WriteLine(text1);
8 }
9 10 public void Main()
11 {
12 if (Class1.<>9__CachedAnonymousMethodDelegate1 == null)
13 {
14 Class1.<>9__CachedAnonymousMethodDelegate1 = new Func<string, string>(Class1.<Main>b__0);
15 }
16 this.MyFirstProgram(Class1.<>9__CachedAnonymousMethodDelegate1);
17 }
18 19 [CompilerGenerated]
20 private static string <Main>b__0(string str)
21 {
22 return new string(Enumerable.ToArray<char>(Enumerable.Reverse<char>(str)));
23 }
24

For the purpose of this post, I will ignore the way the compiler handles anonymous delegates (the reason for the CachedAnonymousDelegate1 thingy and the auto-generated b_0 method).

First look at line 6: the "var" keyword is gone, and all you see is a declaration of a string local variables.

Now look at line 22: Our "Reverse" method shows its true form... A call to the Enumerable.Reverse static method.

In fact, as you can tell, there's no new CLR coming with Orcas. All these new features are strictly compilation features, so only the C# compiler got smarter - the underlying CLR is still at version 2.0.

For more information about extension methods, check out ScottGu's post.

Anyway, I intend to dig in some more in C# 3.0 - especially in Linq, which I have yet to really explore. So more on that later.

Posted by dorony | 2 comment(s)
תגים:, ,

Configuration Weirdness

Lately I've encountered a rather weird behavior when using .NET 2.0's configuration model.

Let's say I have the following custom configuration section:

public class TestConfigSection: ConfigurationSection { public TestConfigSection() { } public TestConfigSection(string testAttrib) { TestAttrib = testAttrib; } [ConfigurationProperty("testAttrib", IsRequired=true)] public String TestAttrib { get { return (String)this["testAttrib"]; } set { this["testAttrib"] = value; } } }

Rather straightforward: Its a config section with one required string attribute. Now, let's use it in a config file:

<configuration> <configSections> <section name="testConfigSection" type="CodeLikeHell.Configuration.TestConfigSection, CodeLikeHell, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c211d86e3b9c35ff" /> </configSections> <testConfigSection testAttrib="testValue"/> </configuration>

Nice and easy, I can get the configuration section with this code:

ConfigurationManager.GetSection("testGroup/testConfigSection") as TestConfigSection;

Now, a question: what will GetSection return for the following configuration file?

<configuration> <configSections> <section name="testConfigSection" type="CodeLikeHell.Configuration.TestConfigSection, CodeLikeHell, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c211d86e3b9c35ff" /> </configSections> </configuration>

As you can see, I didn't actually state the config section in my configuration file, only the declaration for it. You would expect that in this case, GetSection will return null, no? Well, at least I would. But it actually returns a TestConfigSection object, with an empty string as the value for testAttrib. Also, there won't be any runtime exception for the missing required attribute (note that I marked testAttrib as IsRequired=true above). The error will show up only if you explicitly state the configSection in your configuration file without the attribute, as follows:

<configuration> <configSections> .... </configSections> <testConfigSection /> </configuration>

Trying to call GetSection("testConfigSection") will now throw a ConfigurationErrorsException("Required attribute 'testAttrib' not found").

This means that you can't count on the fact that GetSection will return null if the custom config section is not stated in the configuration file, and you can't count on the fact that your "IsRequired" validation will do anything at all.

I didn't find a decent solution for this, although one approach can be to use the DefaultValue property of the ConfigurationProperyAttribute in order to see if the property was initialized or not. Whatever solution you choose, you should be aware of this issue when you test any code that uses custom configuration sections.

Posted by dorony | with no comments
תגים:

FizBuzzing

A huge reaction followed Jeff Atwood's Why Can't Programmers.. Program? post. The post is about how most of the programming jobs applicants can't even solve a simple "FizzBuzz" question which requires you to print all numbers between 1 and 100, while replacing multiples of 3 with "Fizz", multiples of 5 with "Buzz", and multiples of both with "FizzBuzz". Of course, this problem was really not the point of the post, but the readers just couldn't resist writing solutions for it in the comments section. In lots of different ways and different languages (including assembly, SQL and anything else you can think of). It really is quite an amusing read. I especially liked the one in which a guy wrote 100 "print" statements to solve the problem... Now, that's creative if you ask me.

Posted by dorony | with no comments
תגים: