C# - Using references as key in Dictionary

by Fredrik Ljung  

A Dictionaryis used to do quick* lookups of a value using a specific key. Any type can be used as both value and key but if you use your own custom type as a key you need to think of a few things.

*Quicker then say a LINQ-query on a list like MyList.Where(x => x.id == id).Single();

Default GetHashCode() and Equals() are equal if referencing the exact same object

For the following to make sense you need to understand the difference between same object and equal object. The same object is a reference to the exact same object in memory, whereas different objects in memory are only considered equal if you the programmer defines them as such:

Person A = new Person()
{
    FirstName = "Gypsy",
    LastName = "Danger"
};
 
Person B = new Person()
{
    FirstName = "Gypsy",
    LastName = "Danger"
};
 
Person C = B;
 
if (B.Equals(C)) // true
    Console.WriteLine("These references are the same");
 
if (A.Equals(B)) // not true unless Person implements Equals()
    Console.WriteLine("These references are equal");

In the above code Person A and Person B are equal but not the same. They are two different instances of the same type. Person B and Person C on the other hand are the same, they reference the exact same object. Comparison between A and B will not return true unless you override Equals in the Person class. Until then they will only be considered equal if they are also the same. This is because of how comparison works on Object. Object.Equals() will only be equal if the compared Object references the exact same object. The seemingly subtle difference between Object.Equals and Object.GetHashCode() is that GetHashCode() must* return the same value if two Objects are equal.

*With must, I mean should, or you will end up with all sorts of pain trying to use Dictionaries, HashSets, and anything else that relies on GetHashCode() to function properly.

GetHashCode() can return the same value for unequal objects.

Unequal objects usually won?t return the same value for GetHashCode(), but there is no restriction on them to not return the same value. This means that comparison between GetHashCode() can be used to check if an actual equality check needs to performed. If they are unequal it?s safe to assume they are not equal, but if they are the same, an actual equality check needs to be performed. This is why it?s usually good to override Equals in your custom classes, at least if you intend to do any equality comparisons*.

* If you haven?t provided an override for Equals in your objects, if you are using objects you haven?t created, or if you just need a different meaning of equality, you can also use IEqualityComparerwhere it is supported. Dictionary for instance supports equality checks with IEqualityComparer.

Override Equals(Object other) to bring equality to all

So GetHashCode() has returned the same value, now it?s time to prove equality, or inequality if that?s the case. Microsofts guidelines for overriding Equals is to override Equals(), and for added speed bonuses, also define Equals for your specific type:

public Person Class
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
 
    public override bool Equals(object other)
    {
        if (other == null || !(other is Person))
            return false;
 
        return Equals(other as Person);
    }
 
    public bool Equals(Person other)
    {
        return FirstName.Equals(other.FirstName, StringComparison.Ordinal) &&
               LastName.Equals(other.LastName, StringComparison.Ordinal);
    }
 
    // I found the following pattern on StackOverflow. The numbers are
    // prime numbers which magically (or mathematically if you believe
    // in that stuff) creates a fairly good normal distribution of the
    // numbers, which is good for hashing (apparently).
    public override GetHashCode()
    {
        int hash = 17;
        hash = hash * 23 + FirstName.GetHashCode();
        hash = hash * 23 + LastName.GetHashCode();
        return hash;
    }
}

The cost of breaking the guidelines of GetHashCode()

Breaking the rules usually comes with a price. In programming it just about always does. In the case of references as a key, implementing GetHashCode() and then changing the values of the properties used to calculate the has code is a bad thing. However there are a few things you can do to recover. In the case of a Dictionary and HashSet and others I?m sure, you can use IEqualityComparerto work around your proper use of GetHashCode(). If you know your key will change but not how, then perhaps using the object.GetHashCode() is an option as long as you will not try and get values from the Dictionary with a key that?s Equal but not Same.

class PersonComparer : IEqualityComparer
{
    public bool Equals(Person A, Person B)
    {
        if (A.FirstName.Equals("Connor" StringComparison.Ordinal) &&
            A.LastName.Equals("MacLeod, StringComparison.Ordinal))
            return false; // There can be only one
 
        return A.Equals(B);
    }
}

I accidently (this is how I defend that i messed up, an ?accident?) fell into the key change trap recently. I was using Entity Framework entities as keys before I called SaveChanges(). When SaveChanges() was called, all temporary Ids were replaced by the Ids generated in the database. The Dictionary stopped working properly since my override of Equals had the Id as part of the comparison. Since none of the other properties made the object unique, I couldn?t use a IEqualityComparer. The two solutions I came up with was to either wrap the entity in an object and not override GetHashCode(), or to recreate the dictionary using the same references as keys. I decided for the last one since it made the smallest change to my code, and since I was dealing with database calls which are slow, I figured the CPU hit of recreating the Dictionary was small in comparison.

var newMap = new Dictionary();
foreach (var entity in entityMap)
{
    newMap.Add(entity.Key, entity.Value);
}
entityMap = newMap;

Inspiration

by Fredrik Ljung  

When I was young I rather enjoyed writing. I remember that I liked getting the crazy in my head down on paper. Not serial killer crazy, or cork-on-a-fork crazy, just normal crazy, like vampires, and dragons, and such things. Most of the writing was done in class, but since the world was just filled with to many forests to explore and tree houses to build, I never actually got around to write outside of class. Nowadays, more years then I care to count later, I still do enjoy writing. There is just something great when the words pour onto paper, or to keep it in this millennia, through the keyboard, over the wire, and into bytes stored in a cloud. These days it's not the amount of  forests and tree houses that are a problem, instead I seem to have run out of crazy (to write about.).

I have been trying to find things to write about for while now. My evernote account is filled with various attempts at writing, some just small pieces, others almost complete posts, and they all make me cringe when I read them. I find it to be a bit of a personal defeat that I actually allowed myself to put such poor writings into the cloud. It's there, so some part of me must have thought it was good writing at the time! However in the cloud they remain probably due to a mix of self torture and a digital hoarding problem. The problem with them is that they all read like I tried just a little bit to hard. They all have words in them that fit into sentences, but put together they have no flow, and it sounds forced.

Then a few days ago I wrote a post about my top country songs called My country shame, and in some small short moments I reached that sort of nirvana when the text just flows from my brain into the computer. Sometime during that moment I had an epiphatree. I shouldn't try to force inspiration. I should just catch it when it shows up. That aha-moment was great to have, but at the same time rather annoying. In preparation for this blogging thing I have read a few posts about blogging written by bloggers. One of the tings most of them seem to agree on is to do just that, to seize the inspiration when it shows up. For some reason I took it in a broader way, like "pine cones are lovely, I should write about pine cones", without having any idea what it is about the pine cones that I want to tell. Now I realize that what I need to be doing is whenever my brain starts spinning up the crazy engine, to actually let that crazy out.

So I now understand that I shouldn't try to figure out what to write about, but instead, I should try and find out how to be inspired to write about the things I want to write about. How to direct the crazy to the topics where I feel I might have something worth while to say. If all I do is write more of these various ramblings then it doesn't really need to be stored in the cloud. The internet is quite full of inane ramblings without me adding to it.

My Country Shame

by Fredrik Ljung  

Whenever I return home from vacationing in Canada I feel the need to listen to Country music. I assume It's so I can keep the feeling of vacation for just a little longer. This time instead of buying collection CDs, like I've done in the past, I decided to look for the the current country hits online and evaluate them through Spotify. These are my top picks (so far) in no particular order:

Dierks Bentley - Tip It On Back

A bit slower then I usually like, but the song really puts an image in my mind of a nice bar with friendly subdued patrons, and something strong burning at your throat as you "Tip It On Back".

Little Big Town - Tornado

Not your standard Country tune. It has a strong beat, and quite toned down melody. This puts a lot of emphasis on the singing, and to me makes it sound like a backing tune to a cowboy movie, possibly while the poor unsuspecting heroes enter a city full of bad guys.

The Band Perry - DONE.

A good upbeat tune about How to get rid of a bad man. Feels like a sort of pop:ish version of Country. It would probably do ok in Europe, only they would destroy it with blips and blops. I also like their track Better Dig Two from an earlier album.

Brad Paisley - Southern Comfort Zone

It's something quite magical hearing a country singer talk of other places than Dixie! I can just see him on a wheel legged trek through Europe, wearing a big white cowboy hat, a red and white plaid shirt, and light blue jeans with a ridiculously large belt buckle (classy like and all but the size of a hub cap). All cutesy awkward out of place, but then then saving a puppy by borrowing a police-woman's horse and swooping the puppy up just before it gets hit by a truck. A tip of the hat as he returns the horse make the police-woman swoon and forget all about the horse theft.

Blake Shelton - Boys 'Round Here - feat. Pistol Annies & Friends

Wonderfully Redneckie, or how does the line "Chew tobacca, chew tobacca, chew tobacca, spit" suit you? The rest of the song has a kind of carefree laid back feeling to it. A summer song for the less stressful moments. Blake Shelton also brought us Some Beach which should be played in every anger management class ever.

Darius Rucker with Lady Antebellum - Wagon Wheel

I'm not sure if he was Hootie or the Blowfish, but apparently he should have been doing country all along. I would also say I like Lady Antebellum's track Downtown but it's a bit soft, and the hint of old school country stops me from ever admitting to it.

Carrie Underwood - Two Black Cadillacs

It's a good track with some creepy/fun lyrics that gives me a The Dixie Chicks - Goodbye Earl sort of vibe.

Miranda Lambert - Mama's Broken Heart

There is a fair share of Country songs about women being strong, but having to sort of explain why, or apologize for it, or more likely, having to point out that they don't have to apologize for it, thus in a sense apologizing for it (understandable subject matter considering where the songs are from). Mama's Broken Heart does neither. This is about a woman going slightly crazy over a breakup, while ranting about her crazy mothers must be a presentable lady attitude. I can almost smell the whisky she's downing (no tipping it back here). A woman being human.

And then there was Lee Brice - Parking Lot Party. I can't make up my mind about this one. It has a some sort of appeal. It has a nice groove to it and all but there's just something about it that rubs me the wrong way. Perhaps it's the fake crowds cheering, or perhaps it's the fake radio intro or that his own name gets mentioned. All I know is that I have listened way more times to it then it deserves trying to figure it out (twice while writing this.).

Here's hoping my need for country music ends soon so I can go back my normal life.

The importance of using - well using

by Fredrik Ljung  

In our company, like many others I'm sure, we have a lot of small utility apps filled with legacy code. For us legacy code means code that lacks unit tests, and is full of anti-patterns. Global variables, functions with 100+ lines of code, static classes doing the brunt of the work, and a naming strategy that includes such marvels as MyFunction(), litter the code. It's very easy to judge the code on these failures, but the code has been in production for many years. It might be held together with staples and duct tape but years of small necessary tweaks means it works well for what they are used for. Occasionally, however, I get reminded of just how fragile this code base is.

The update loop

About a year ago I was out on site at a customer helping out with the implementation of our application. The application is an average size handheld application running on Windows CE. While testing I came across some issues which were easily solved by using newer hardware drivers that the OEM ships for the handheld. I decided to update the drivers, rebuild the solution, and publish the new files through our update solution. The update solution  is a rather simple service that basically keeps an application folder on the handheld in sync with a dedicated folder on the server. The client application achieves this by firing up an update utility and then shuts itself down and lets the updater handle it from there. The update utility has been used in plenty of our solutions for years without any problem, and it had worked fine for the past six months at the current customer location. However after applying the new update to the client it stopped working. Something in the process failed and the updater initiated a rollback and restarted the client. The problem though was that the client would restart the update and the entire process would repeat itself. The error messages where vague at best and no logging existed. My only clues were that the first two files updated ok then the process would freeze and after 30 second or so it would fail and rollback. As my day at the customer was all but over I didn't have time to find out why it wasn't working. I decided to update all handhelds manually and promised myself I would look at the problem at the first available moment.

Reminded of my procrastination

Fast forward one year and obviously I never got that available moment to fix the update problem. It never seemed important enough to take care of. Instead necessity hit me at a most inconvenient time. The customer had been stuck in a delayed change of ERP systems and so our small sub project also got put on hold. Recently things started moving again and I returned to the project to get the application up to speed with the rest of the project. As I'm sure you have guessed by now, I came to a point where I needed to publish updates to the application that consisted of more than two files. Since I hadn't touched the update utility in the past year the update yet again failed as it tried to update more than two files. I realize I have to put my current work on hold and go digging around in some legacy code.

Disposing of the culprits

The code was a shining example of the state of the legacy code we have amassed. The update applications Main function was about 60 lines and the rest of the code was all in static functions, ranging 20 to 50 lines of code. It's not a large project by any means, consisting of one class, Program, at about 400 lines and an easy enough structure to understand. I spotted the first hint of the problem on the third row in Main(), where the creation of the reference to the web service was not wrapped in a  using() statement, and no dispose in sight. I spent about an hour refactoring the code and found another few undisposed objects. Those were just a reflection of the actual problem, and below is a snippet from the function that broke the utility.

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream s = response.GetResponseStream();
using (FileStream fs = File.Create(file))
{
    ...
}

The code above resided in a function that was called for every file to be updated. Once I added using() for HttpWebResponse response and for Stream S the problem disappeared. My assumption is that the lack of calls to Dispose() for response and s kept the connections to the server active. With a limit of two concurrent connections, the application timed out trying to create the third, and then initiated a roll-back.

And that is why using using()is best practice when possible.