There is more than one way to linq that

Eric Gunnerson has a post in which he responds to Justin Etheredge regarding “Is Programming A Generic Skill?

I’ll just say that I agree with them both. There are differences between ability, proficiency and mastery.

A Java programmer can jump into C# and be an able C# programmer immediately. It will take time to become proficient and even more time to develop mastery.

I am proof of this with python. I’ve been an able python programmer for over 10 years now(actually closer to 15), but I never spent enough time in python to call myself proficient and I’m certainly far from a master.

But the thing that Eric said which triggered me to write this is not the generic skill discussion with Justin, it is instead a remark that Eric said about Perl, “… because of TMTOWTDI”.

C# is very much becoming afflicted with There is More Than One Way To Do It. It certainly is both the language and library.

Consider LINQ. LINQ to Objects is a new way to do something which everyone has done differently in the past. When new programmers are exposed to linq, I often hear the question “When do I use linq?” The answer I give is typically “whenever you would use a for loop or foreach loop and if you can’t, figure out how you can".

If we throw away the ‘idiomatic code” to which Eric refers, then a giant bucket of TMTOWTDI is thrown in our face. Do we use properties or fields, events or delegate fields?

For public interfaces, FxCop helps a great deal with guidelines for these things and helping to learn the idioms of the language and framework, but for other things, you are left to yourself. That is why reading others source code is so important. (see the weekly course code)

Expand into libraries and TMTOWTDI explodes. From MSFT alone there is Remoting, Web Services (asmx), WSE, WCF, RIA Services, ASHX, ASP.NET Data Services, all of which have some overlap. Then for data access there is ADO.NET, Linq2Sql, Entity Framework. Even within ADO.NET alone, TMTOWTDI. Do you use a reader? Table Adapter with DataSets? Strongly Typed DataSets?

Open to non MSFT and TMTOWTDI explodes again, to the point where I won’t bother listing anything. There is too much.

I think that library TMTOWTDI will always exist. Even Python has SqlObject, SqlAlchemy and ORM as parts of other frameworks like Zope and Django. But language TMTOWTDI is reasonably well mitigated in Python. This is stated in a single line in PEP20 – The Zen of Python

There should be one—preferably only one –obvious way to do it.

C#, perhaps because it was not a goal and because of its C/Java/Delphi roots, has never had that. There has always been TMTOWTDI in C#.

How useful are your error messages?

F.cs(334,8): error CS0539: ‘I.M’ in explicit interface declaration is not a member of interface
F.cs(20,15): error CS0535: ‘C’ does not implement interface member ‘I.M(out string)’

This is a fun example of a poor error message, and I don’t mean because I named my file F, my interface I, my method M and my class C.

Its poor because the underlying code looks like this:

interface I { bool M(out string); }

class C:I { void M(out string); }

Sure, this is obvious now what is going on, I have void, but I should have bool, but my error message doesn’t include that when it shows the type signature.  Now consider what happens when interface I is in an assembly which is given to me. I do not have its source, and there is no documentation. My means of finding the signature of this method are three fold:

  1. lean on visual studio press F12 to go to reference of the interface and VS shows me type signatures
  2. use reflector
  3. monodis mylibrary | grep MethodName

I usually use #1, which is probably why I’ve never seen how horrible this compiler error message is until today. Today, I used #3.

* monodis is from Mono

Internet Explorer 8 in Windows 7 is Not All Bad

The number one feature that has been in Opera for longer than I can remember, and in Firefox via add-in or by default for nearly as long, is that of restoring a session when the browser or system crashes.

I lean on this feature. I use browser tabs as a todo list. Sometimes I have to-read tabs open in my browser for only minutes, and other times those to-read tabs are around for weeks and into months.

Internet Explorer was a no-go on this feature, until I noticed it today.

My laptop (I blame hardware – or poor Dell drivers) did not go to sleep when I shut the lid this evening. After a 5 mile bike ride and a 12 mile car ride home in a well insulated back pack, the laptop was frozen and pretty warm when I got home and unpacked. I had to reboot.

As soon as I logged in I remembered that I had left an Internet Explorer window open with something I wanted to read. I cursed because I thought I would have to find it and I usually struggle finding things in browser “history”.

I was surprised when I was greeted with a “restore last session” prompt from Internet Explorer.

Good job on a great feature, Internet Explorer team.

Will I be using IE as my default browser? Absolutely Not. RequestPolicy and NoScript are required browser add-ins for my daily browser usage.

nmap can open device eth15, but only if you let it

This is here as a note to myself to not be stupid.

I’ve remembered at forgotten this at least 4 times and so that makes me stupid for not remembering.

When nmap on win32 tells you that “dnet: Failed to open device eth15”, it is really suggesting that you run it as administrator.

You need to be administrator to access the network device at this level.

I can’t use var in my foreach loop

A month ago, I asked a coworker to implement IEnumerable<blah> on a blahCollection type that we had implemented back in 1.1. We had only recently moved to the C# 3.0 compiler for this project and I was a little surprised that I wasn’t able to use the var keyword inside a foreach statement of this type. (I could use it, but it types the object as object instead of a strong type, which is effectively “cannot use it”.)

Its a combination of “we used to implement our own iterators” and the way the foreach finds the GetEnumerator method. foreach doesn’t actually work off of IEnumerable or IEnumerable<T>. It just looks for a GetEnumerator method. So when you implement IEnumerable<T>, foreach won’t find it if it is an explicit implementation. It needs to be an implicit implementation. But this will conflict with the old IEnumerable implementation, and so the change is a break in binary compatibility. Its a small price to pay for use of new language features.

note: Bill Wagner told us all of the above but wrapped it in a <guess> tag when he emailed us.

I wrote a test to show the behavior. Huge thanks to someone (I don’t recall who) in #csharp on freenode who helped me in creating the CompileTimeType method. Its very different to me to use the compiler in this way.

using System;
using System.Collections.Generic;
using System.Collections;
using NUnit.Framework;
namespace Scratch.IEnumerableFixtures
{
    [TestFixture]
    public class foreachFixture
    {
        [Test]
        public void implicitIsStrong()
        {
            foreach(var item in new I())
                Assert.AreEqual(typeof(int), CompileTimeType(item));
        }
        [Test]
        public void explicitIsWeak()
        {
            foreach (var item in new E())
                Assert.AreEqual(typeof(object), CompileTimeType(item));
        }
        [Test]
        public void noInterface()
        {
            foreach (var item in new N())
                Assert.AreEqual(typeof(object), CompileTimeType(item));
        }
        [Test]
        public void noInterfaceGeneric()
        {
            foreach (var item in new NG())
                Assert.AreEqual(typeof(int), CompileTimeType(item));
        }
        public Type CompileTimeType<T>(T item) { return typeof(T); }
        class I : IEnumerable<int>, IEnumerable
        {
            public IEnumerator<int> GetEnumerator() { yield return 1; }
            IEnumerator IEnumerable.GetEnumerator() { yield return 1; }
        }
        class E : IEnumerable<int>, IEnumerable
        {
            IEnumerator<int> IEnumerable<int>.GetEnumerator() { yield return
1; }
            public IEnumerator GetEnumerator() { yield return 1; }
        }
        class N { public IEnumerator GetEnumerator() { yield return 1; } }
        class NG { public IEnumerator<int> GetEnumerator() { yield return
1; } }
    }
}

Outlook 2007 autodiscover for the rest of us

Outlook 2007 has a new feature which is provided to it by default only by Exchange 2007.

I recently thought of giving Outlook a try instead of Windows Live Mail. Of course, the geek in me wanted my Outlook 2007 first run experience to be awesome. I wanted autodiscover to work for me.

It turns out if you read a KB article and a technet article you can figure out that for 99% of POP/IMAP/SMTP installations, placing an autodiscover.xml file at a url of http://myemail.com/autodiscover/autodiscover.xml or at http://autodiscover.myemail.com/autodiscover/autodiscover.xml is all that is needed. The format of the xml is very simple.

<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
  <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
    <Account>
      <AccountType>email</AccountType>
      <Action>settings</Action>
      <Protocol>
        <Type>IMAP</Type>
        <Server>mail.xmtp.net</Server>
        <Port>993</Port>
        <DomainRequired>off</DomainRequired>
        <SPA>off</SPA>
        <SSL>on</SSL>
        <AuthRequired>on</AuthRequired>
      </Protocol>
      <Protocol>
        <Type>SMTP</Type>
        <Server>mail.xmtp.net</Server>
        <Port>25</Port>
        <DomainRequired>off</DomainRequired>
        <SPA>off</SPA>
        <SSL>on</SSL>
        <AuthRequired>on</AuthRequired>
        <UsePOPAuth>on</UsePOPAuth>
        <SMTPLast>on</SMTPLast>
      </Protocol>
      <Protocol>
        <Type>POP3</Type>
        <Server>mail.xmtp.net</Server>
        <Port>995</Port>
        <DomainRequired>off</DomainRequired>
        <SPA>off</SPA>
        <SSL>on</SSL>
        <AuthRequired>on</AuthRequired>
      </Protocol>
    </Account>
  </Response>
</Autodiscover>

 

Do that, and the next time an Outlook2007 client tries to configure itself, it will.