Archive for the ‘C#’ Category

Why I Love C# More Than I Care About Ruby

Thursday, July 15th, 2010

@robconnery I’m really glad that you are excited. I think anytime someone is healthily and safely passionate about something, it can only be a good thing.

Rob has a great post where he lists 4 cases where he likes Ruby and compares to the same thing in C#. Case 1 Expressiveness: Rob likes the unless statement and the post expression if statement. Case 2: Rob likes Gems. Case 3: Rob likes simple things. Case 4: Rob likes sending messages, open classes and method missing.

Python and Perl already did all this, so why Ruby?

Case 1 and 3 were true in python when i started writing it in 1996 and case 1, 2 and 3 were true in perl when i started writing it in 2000. I’m sure case4 is true in both python and perl too, but I never went that deep into either of them. Much like in Ruby, you don’t have to go that deep to get things done.

I am of the opinion that if you have never seen a dynamic typed language before, or maybe a dynamic typed language other that BASIC or VB before, that Ruby has all of the appeal which you tout. However, there are some of us who write C# because we actually like it, we write desktop applications, and find it to be the best static and strong typed language around. We came to C# and were super impressed because the weak typing of C wasn’t there. The rough edges of C++ wasn’t there and for nearly all applications there is no performance difference and sometimes the GC and managed environment actually gives a boost in performance over some of the bad C++ we were writing before.

So should someone who has never written in Perl, Python, Pike and PHP go try out Ruby… absolutely… get the exposure.

Alternatively, if you have done some Perl or Python and now you are a C# guy. Ruby might not seem so impressive. In fact, it looks more like the same thing with a new coat. I can’t tell what the hype is about. There isn’t much new and different.

All that said, after years of Perl, learning C# was a challenge, especially since I was using it to solve many of the same problems for which I had been using Perl. WHY? was I doing it that way? Well I wanted Windows Forms UI front ends on my Perl versions of programs there were ultimately just sed/awk/grep and some ldapsearch/ldapadd/ldapmodify commands. Not commands really, but calls to libraries.

There is a good reason that the “simple things” aren’t AS simple.

What I learned was that there is a damned good reason that Case 3 “The Simple Things” were a little more complex in C#. The separation of stream and textreader abstract types in C# make huge sense once you realize that doing the same thing in perl or python (or ruby) can be a bit of a hassle. The organization of decorator streams in the .NET BCL just makes sense. Want to compress? Decorate with the stream compressing class. Want to encrypted? Decorate with the stream encrypting class. Want to do both? In either order? Decorate appropriately.

I do share Rob’s opinion. It is a little prettier in Ruby. I’ve already gone on record as saying that “var” in C# should be optional. In VB6 the Let statement was optional. In VB.NET the Let statement is no supported. IMO C#’s var isn’t much different than VB.NET’s Let and Dim. Sure would be nice if it were optional.

I’ve also requested static imports so that we could do things like just call the open method instead of saying File.Open. When you are in a nice tiny singly responsible file, it just makes sense.

These things don’t change my ability to write code.

On .NET’s lack of a CPAN, Cheeseshop, Gem equivalent: YES! YES! YES WE NEED IT NOW!

I can’t say anything other than .net needs CNAN (comprehensive .net archive network) or maybe CCAN (comprehensive CIL archive network). I can’t decide which name I like better.

As for metaprogramming, I think that Python, Perl and Ruby’s ability for runtime metaprogramming will continue to be far beyond anything you see in the C# world. That is not say that metaprogramming is not possible in C#. Its just very different. Its typically compile time metaprogramming. Thanks to the addition of T4 in VS2008 and 2010, metaprogramming in C# is readily available and powerful.

I could go on and insert above about how I learned to love the .NET RegularExpression API after having it blow my mind in comparison to perl’s. Or about how poorly documented the System.DirectoryServices API is, but that once I got it I loved it so much more than Net::LDAP. Or about the extreme pain in building CPAN modules on a Sun Sparc and how installing Mono and using Visual Studio and C# was actually easier than making Perl work properly.

But rather than elaborate on those things, I’ll end by saying, yes, Ruby is awesome, if you have never seen any of the things which make it awesome before.

C# 4 Optional Parameters Limits Default Value

Sunday, July 4th, 2010

Jon Skeet has an excellent C# 5 talk video from the recent Norwegian Developer Conference. Go watch it.

When he showed Default<T>, I immediately thought it was just an variation of Option<T> or F#’s option type, but with added default value logic. Its cool.

He was asking for compiler support so that things like this would be possible.

Default<int> a = 1;

Well, I thought, you don’t need compiler support for that, just add an implicit type converter to your definition of Default<T>

        public static implicit operator Default<T>(T value)
        {
            return new Default<T>(value);
        }

No worries, right?

Oh I was so wrong. While this will work for the regular above statement, it won’t work as a default parameter value.

     class Things { public Things(Default<int> a = 5) { } }

This provides a wonderfully descriptive error (I love this compiler) which says “a value of type ‘int’ cannot be used as a default parameter because there are no standard conversions to the type ‘Default<int>’”

Now I’m crying? Why the limit? Instead of Jon’s request for awesome Default<T> support in C# 5, I request considering implicit type converters on optional parameter default values.

WlanChannelInfo aka Windows 7 Net Stumbler aka Wifi Channel Info

Friday, July 2nd, 2010

I finally got around to updating WlanChannelInfo. It started because I wanted to play with some .NET 4 beta features and I also struggled with getting a simple net stumbler running. I figured that Windows had to have something better to offer, and it turns out that in windows 7 the WLAN API was updated to expose everything that I cared about. I really only want to see what WIFI channel’s my neighbors are on so that I can move my WIFI AP to an unused channel.

http://wlanchannelinfo.codeplex.com/

I finally updated it to use a .NET release instead of a .NET 4 beta, but when I did, I decided that I didn’t need .NET 4. I just stuck to using 3.5 so that this app will run out of the box on Windows 7. No need to get .NET 4 to run this. I figure my parents might have windows 7 but probably won’t have .NET 4 installed just yet. Maybe someone else’s parents would have the same issue, and since the download is only 19KB… yes, 19KB… since the app is dead simple and does nothing but use existing WPF controls and p/invoke into the WLAN api (via the ManagedWifi.dll also on codeplex) its *TINY*.

Let me know if you find this useful.

Method I Wish Was There: AsUri

Monday, May 31st, 2010

I never got used to the .NET Uri type. It seems like I only had to use it occasionally and even then where I really only wanted to type a string url.

public static Uri AsUri(this string uri) { return new Uri(uri); }

This way I can just add a AsUri() when I forgot that I was supposed to pass a Uri instead of a string.

webclient.DownloadFileAsync( “http://blah.com”, filename );

doesn’t compile and so I can scratch my head once again and replace it.

webclient.DownloadFileAsync( “http://blah.com”.AsUri(), filename );

I like trivial things :)

Method I Wish Was There: IsWithin

Friday, May 28th, 2010

I don’t think I like the name, but I couldn’t come up with something better.

public static bool IsWithin(this DateTime datetime, TimeSpan distance) {
  var now = DateTime.Now;
  return (now – datetime).Duration() < distance;
}
public static bool IsWithin(this DateTime datetime, TimeSpan distance, DateTime now) {
  return (now – datetime).Duration() < distance;
}

Coupled with extension methods from yesterday you can write code like this:

if ( postDate.IsWithin(24.Hours()) ) { … }

nice and readable.

Method I Wish Was There: Minutes, Hours, Seconds

Thursday, May 27th, 2010

Ok, the ruby lovers will laugh, the ruby haters will, well, hate.

public static TimeSpan Minutes (this int minutes) {
  return new TimeSpan(0, minutes, 0);
}
public static TimeSpan Hours (this int hours) {
  return new TimeSpan(hours, 0, 0);
}
public static TimeSpan Seconds (this int seconds) {
  return new TimeSpan(0,0, seconds);
}

So that now I can write readable code like this:

var fiver = 5.Seconds();
var fivertoo = 5.Hours();
Assert.That( fiver.IsLessThan(fivertoo) );

Method I Wish Was There: DataGridView.GetDisplayIndexToPropertyNameMap

Wednesday, May 12th, 2010

Alright, I’ll admit it, this one is rather obscure and only useful if you are doing strange things with a Windows Forms DataGridView.

I like this method because I think its a good use of Fold… err.. I mean Aggregate. I’m convinced Aggregate is an underutilized method so far by .NET developers.

In this case I like it because I can state what I want to do in a single statement rather than multiple statements.

public static IDictionary<int, string> GetDisplayIndexToPropertyNameMap(this DataGridView datagridview)
{
  var boundColumns = 
          datagridview.Columns.Cast<DataGridViewColumn>().Where(c => null != c.DataPropertyName);
  return boundColumns.Aggregate(
                new Dictionary<int, string>(),
                (a, b) => a.Insert(b.DisplayIndex, b.DataPropertyName));
   }

Notice the use of yesterday’s Dictionary.Insert so that we return the Dictionary at every iteration of the Aggregate*.

I find this MUCH more readable than if the Aggregate statement had been

return boundColumns.Aggregate(new Dictionary<int,string>(),
   (a,b) => { a.Add(b.DisplayIndex, b.DataPropertyName); return a; } );

The curly braces for the block lambda syntax and the return statement inside them really take away from the readability IMO.

* Note that this is why I put Insert explicitly on Dictionary instead of IDictionary. C# 3’s type inference is not good enough to figure out that we would want the signature of Aggregate to be IDictionary<int,string> instead of Dictionary<int,string> if Insert returned an IDictionary

Method I Wish Was There: Dictionary.Insert

Tuesday, May 11th, 2010

Yes, this is a horrible name. If you have a better suggestion, I’m very welcome to it.

Here is the point: I want a method on Dictionary that does what Add does, but returns the dictionary instead of void. That way I can do this.

var d = (new Dictionary<string,string>()).Insert(“hi”,”mom”).Insert(“hello”,”dad”).Insert(“peace”,”sista”).Insert(“word”,”brotha”)

And yes, I know that C# 3’s initializer syntax lets me do this instead:

new Dictionary { { “hi”,”mom” }, {“hello”,”dad”}, {“peace”,”sista”}…}

BUT… that only works with a constructor. Tomorrow’s edition will show why I want a method instead of an initializer.

* I didn’t know that initializer is not a dictionary word. I love when fields (programming) extend their own words.

Nullables are evil

Tuesday, May 4th, 2010

[TestMethod]
        public void NullYourMom()
        {
            var x = (int?)Activator.CreateInstance(typeof(int?)) ;
            Assert.IsFalse(x.HasValue);
            try { x.GetType(); }
            catch (NullReferenceException) { Console.WriteLine("oh shit"); }
            if (x.HasValue)
                Console.WriteLine(x.GetType());
            x = 1;
            Console.WriteLine(x.GetType());
            Assert.AreEqual(null, x);
        }

Lord help me

Crazy Things I Did Before Generic Variance

Friday, April 23rd, 2010

public class stuff : IEnumerable<Thing>, IEnumerable<IThing> { … }
public static void Main() {
  stuff s;
  var names = s.Select(t=>t.Name);
}

And even though System.Linq is imported, I still get an error “stuff" does not contain a definition for Select and no extension method ‘Select’ accepting a first argument of type ‘stuff’ could be found (are you missing a using directive or an assembly reference?)

Well, no, but LINQ and extension methods on IEnumerable<T> doesn’t work when the T is ambiguous. If I were to cast the above “s” to one of IEnumerable<Thing> or IEnumerable<IThing>, then I could use LINQ, but until I do, I get nothing. The error message isn’t all that helpful either.

My general recommendation: don’t do this.