All posts by Mike Adelson

About Mike Adelson

I'm a software engineer at Applied Predictive Technologies in Washington D. C., where I work on "big data" analytics and .NET web development. In my spare time, I enjoy reading, working on various side projects, and answering questions on StackOverflow.

Implementing Equals() and GetHashCode() in C# 7

Much like C# 6, C# 7 seems to be all about making common tasks just a little bit easier. Recently, I blogged about some of the ways I’d found myself using throw expressions. This time, it’s implementing the old standbys Equals() and GetHashCode().

The old way

Let’s say we had a simple class:

class ProductInfo
{
    public Customer(int productId, string style)
    {
        this.ProductId = productId;
        this.Style = style;
    }

    pubilc int ProductId { get; }
    public string Style { get; }
}

In C# 6, I would have implemented Equals() and GetHashCode() like so:

public override bool Equals(object obj)
{
    var that = obj as ProductInfo;
    return that != null
        && this.ProductId == that.ProductId
        && this.Style == that.Style;
}

public override int GetHashCode()
{
    return unchecked((3 * this.ProductId) + EqualityComparer<string>.Default.GetHashCode(this.Style));
}

The new way

Here’s what it looks like in C# 7:

public override bool Equals(object obj)
{
    return obj is ProductInfo that 
        && (this.ProductId, this.Style).Equals((that.ProductId, that.Style));
}

public override int GetHashCode() => (this.ProductId, this.Style).GetHashCode();

Just a little bit nicer!

Yes, the tuple trick could have been done previously using System.Tuple or anonymous types. However, those are both classes which means creating them requires a heap memory allocation. This might not be ideal for a type which is heavily used as a dictionary key or set member. The new tuple literals are value types, which means that no heap allocation is required. And of course, creating a tuple literal is just a tad bit more concise as well.

Scripting in C#

I’m probably one of the few programmers out there whose go-to scripting language is… C#. To many, especially those who don’t use C# on a daily basis, this will sounds crazy. How can you possibly be productive if each script requires loading up Visual Studio, creating a new project with it’s associated dozens of files and folders, and pounding out all of the namespace and class boilerplate required to run a few lines of code? Wouldn’t something like Python or Powershell or even Bash be preferable?

The answer is that modern tooling and language features have greatly reduced the startup overhead to rapidly authoring, running, and maintaining C# scripts.

Continue reading Scripting in C#

7 ways to use C# 7 throw expressions

One of the least-heralded new features in C# 7 is also one of my favorite: throw expressions. With this feature, you can now use a throw clause in a number of places where you couldn’t previously. Like many of the recent C# changes, this won’t revolutionize your coding by any means, but it will consistently make things a little bit cleaner and more concise. Here are a few of my favorite new ways to throw exceptions.

Continue reading 7 ways to use C# 7 throw expressions

Mysterious deadlocks and leaking isolation levels

Recently, a user reported some difficulty using our software. Investigating our error logs, we determined that the culprit was a classic one: SQLServer deadlocks. What made less sense were the two deadlocking queries: one query was an insert into two tables (one via trigger). The other query was a read which joined those same two tables. While there are various ways that this can cause a problem, it shouldn’t have been a persistant issue here and hadn’t ever been one in the past. What was going on?

Continue reading Mysterious deadlocks and leaking isolation levels

The Cult of DRY

As developers, most of us are inducted into the cult of common code and Don’t Repeat Yourself (DRY) early on in our software engineering educations and careers. This was certainly the case for me. The idea sticks with us because it just makes so much sense: why write more code when you could write less? Why slog through making changes in dozens of places when you could have updated a single bit of centralized logic? Why re-invent the wheel when you can use a battle-tested implementation that already exists?

Over time, however, I’ve come to see cracks in this philosophy, or at least the absolutist version of it. DRY is a powerful software engineering principle, but it is not the only software engineering principle. As codebases and teams get larger, a religious adherence to DRY can be crippling to maintainability and development time.

Continue reading The Cult of DRY

Random numbers in C# .NET: a primer

On the surface, .NET’s Random class seems comparable to the random number APIs in other frameworks. However, it has a number of quirks that can make it tricky to use correctly. With randomness, bugs can manifest quite subtley: rather than an exception you might just end up slightly biased load balancing or a playlist shuffle that picks the same song first more often than not. Therefore, it’s worth taking the time to make sure you know what you’re doing! This post covers the basic usage patterns for the random class, as well as the gotchas and how the MedallionRandom NuGet Package can help fill in the gaps.

Continue reading Random numbers in C# .NET: a primer

Generic Tree and Linked List Traversal in C#

When you think of traversing a tree, what comes to mind? Recursion? Looping with a stack? While both of these methods work perfectly well, neither has the elegance, convenience, composability, and laziness of IEnumerable-based traversal using LINQ. Luckily, it isn’t hard to “factor out” the mechanics of traversing trees and tree-like data structures such that we can cleanly process such objects with LINQ without writing lots of boilerplate code first. In this post we’ll look at a couple functions in the MedallionCollections NuGet package that do just that.

Continue reading Generic Tree and Linked List Traversal in C#