.NET Misconceptions Part 1
This is a little mini-series I’ve wanted to do for a while. I wanted to go through some common misconceptions about the way things work in .NET in order to help people get through problems instead of working around them. I have a few parts planned, but we’ll see how many I can come up with.
So this first one is about garbage, the most overrated fear of a lot of game developers. The big misconception for this post is the idea that you can’t use an enum as the key in a Dictionary<TKey, TValue> without generating garbage each time you index in. This leads a lot of people to do ugly hacks like casting the enum to an int or short (possibly even with a subclass or wrapper to do it for them). This is ugly and hacky and ruins the type safety that generics bring because you have allowed the key to be any integer or any short.
Instead of this silly work around that leads to ugly code that is harder to write and annoying to read, just pass an IEqualityComparer<T> to the dictionary’s constructor, where T is the same type as the dictionary key (and yes, it will enforce this at compile time so you can’t pass any other kind of IEqualityComparer<T> in even if you wanted to).
So as an example, let’s say I want to store my own dictionary of GamePadStates so that way I can always grab them but only update from the gamepad’s themselves once per frame. The first thing we’ll do is just make up a static class to contain this functionality for us:
public static class InputManager
{
public static readonly Dictionary<PlayerIndex, GamePadState> CurrentStates;
static InputManager()
{
// instantiate the dictionary
CurrentStates = new Dictionary<PlayerIndex, GamePadState>();
// add the empty values to ensure all keys are present
CurrentStates.Add(PlayerIndex.One, new GamePadState());
CurrentStates.Add(PlayerIndex.Two, new GamePadState());
CurrentStates.Add(PlayerIndex.Three, new GamePadState());
CurrentStates.Add(PlayerIndex.Four, new GamePadState());
}
public static void Poll()
{
CurrentStates[PlayerIndex.One] = GamePad.GetState(PlayerIndex.One);
CurrentStates[PlayerIndex.Two] = GamePad.GetState(PlayerIndex.Two);
CurrentStates[PlayerIndex.Three] = GamePad.GetState(PlayerIndex.Three);
CurrentStates[PlayerIndex.Four] = GamePad.GetState(PlayerIndex.Four);
}
}
It’s a simple class but suits the purpose. We have a dictionary of the states and a Poll method that takes care of polling the input. We would then set this up to Poll once per frame (at the start of our Update method) and then simply reference the CurrentStates dictionary everywhere else.
At this point, many people would start screaming “But those enums are going to cause garbage!!1!”. Sure, right now they definitely are. But we can fix that. Let’s make a new class real quick:
public class PlayerIndexEqualityComparer : IEqualityComparer<PlayerIndex>
{
private static PlayerIndexEqualityComparer defaultInstance;
public static PlayerIndexEqualityComparer Default
{
get
{
if (defaultInstance == null)
defaultInstance = new PlayerIndexEqualityComparer();
return defaultInstance;
}
}
public bool Equals(PlayerIndex x, PlayerIndex y)
{
return x == y;
}
public int GetHashCode(PlayerIndex obj)
{
return obj.GetHashCode();
}
}
This is a pretty simple class that just implements IEqualityComparer<T> for the PlayerIndex type. The static stuff is just a little extra I tossed on so that we can just reuse the same object if you want to have lots of dictionaries or other types that use IEqualityComparer<T> for the PlayerIndex type.
Anyway, let’s go back to the InputManager and alter the instantiation of the dictionary to this:
CurrentStates = new Dictionary<PlayerIndex, GamePadState>(PlayerIndexEqualityComparer.Default);
And now we no longer have garbage.
That’s really all it takes. You can make an IEqualityComparer<T> for any enum you want to use as a key in a dictionary and never worry about boxing and garbage ever again. Just please stop casting enums to ints/shorts as keys. That’s ugly.
Edit: For a bit more clarification on why you get boxing to begin with and why this fixes it, please see my first comment below (comment #2).
Possibly Related Posts
(Automatically Generated)Basic Handling of Multiple Controllers
Extending GamePadState
Spice up your PC input with extension methods
XmlSerializer Misconceptions Part 1
IDictionary + XmlSerializer = Epic FAIL

It’s always cool to find solutions to common misconceptions about XNA, NET and C#, they help newcomers quickly avoid picking up bad habits and practices. Far too many online tutorials and books on XNA simply speak about how to use the XNA API in general terms, avoiding the less obvious topics and pitfalls to be aware of, such as garbage generation, why it’s bad practice to use XNA components for all your objects etc.
However, I feel that many newcomers to XNA might also be fairly new to C# and .NET, so would it be possible when covering topics like this one to not only describe the immediate ’solution’, but also have a preliminary chat about the ‘Why’ you need to do it and some talk of ‘How’ it works?
I’m not familiar with the IEqualityComparer interface and the MSDN help files are less than enlightening to this newcomer, so it’s not entirely clear why your solution works without some background into the problem it’s solving. For example I thought in using Generics you avoid any boxing / unboxing gargage generation purely by virtue of using a Generic because it’s using a specific type rather than System.Object?
Keep up the great work, I for one hugely appreciate it.
Good point. The garbage that occurs is because of boxing/unboxing costs under the hood. The dictionary requires an IEqualityComparer<T> in order to work properly because it obviously needs to be able to compare keys. Since there isn’t a way to constrain your TKey type to having implemented the == sign, you need some other way of testing equality.
IEqualityComparer<T> lets you determine if two objects are equal. That’s really all the interface is for. A dictionary will provide a default IEqualityComparer<T> using the EqualityComparer<T>.Default property if you do not provide one on your own. The comparer that is generated first determines if T implements IEquatable and if so uses that to determine equality. If T does not implement IEquatable (as is the case for all enumerations) the EqualityComparer<T>.Default will have an implementation that relies on the object.Equals override available for the type, which for enumerations means they take in type object. Passing the enumeration as an object will cause boxing and thus create garbage.
Thus if you pass in your own implementation of IEqualityComparer<T> the dictionary will use that instead, so if we just give it a comparer that doesn’t rely on the object.Equals method, we avoid it using the default implementation and the garbage it creates.
Aha, I understand now.
I guess the moral of the story for inexperienced C# and .NET coders learning XNA is to keep an eye out for all .NET data structures and classes whose implentation might be using that pesky System.Object as a default type and, where possible, provide your own specific type based on the needs of your program.
I’m slowly realising the generalised nature of System.Object can be great for making life somewhat easier for the more sedentary event-driven applications, or maybe even in areas of XNA code that are called once, but you sure as heck do not want one living in tight code loops such as Update and Draw that are called frequently
Thanks for taking the time to give some insight into this.
Instead of rolling your own hand-written EnumComparers, you can use a generic implementation that fits all enums. It’s not trivial to write, but I provided 2 examples that use lightweight code-generation techniques in a CodeProject article that I recently wrote.
You should check it out here:
http://www.codeproject.com/KB/cs/EnumComparer.aspx
The problem with that solution is that it relies on Reflection.Emit which doesn’t exist on the Xbox 360. It’s also quite complex and while it might save you time if you utilize a lot of enums as keys, it’s probably faster to just roll a comparer when you need one since most people likely only need a few of them. If you create lots of them, you could probably also make a VS file template that generates the whole thing for you, leaving you to just fill in the type.
Oh, I didn’t know the xbox 360 was using the compact edition of the framework.
The main problem I see with this solution is that most developers are lazy (which includes me sometimes). Implementing an entire new class just to get an equal statement to work more efficiently seems crazy (that’s a lot of typing). Especially when the underlying data type of an Enum is an Integer. Why doesn’t the framework do this for us automatically? Casting it to an int is a lot easier and developers are going to keep doing it. I do agree with you btw, people just aren’t going to do it.
If I have EnumA.Value that happens to be equal to integer 1 and EnumB.Value that happens to be equal to integer 1, the framework automatically casting those to int to compare is going to either require additional instructions to ensure the two integers stemmed from the same enumeration (thus being less performant) or it will have to ignore type safety and consider EnumA.Value to be equal to EnumB.Value simply because their underlying integer values are the same. The third option is to box and compare using Object.Equals which is exactly what the framework does automatically, but this incurs the boxing/unboxing cost.
People are free to ignore it, but considering you could easily copy/paste the code and change a few types it’s rather quick considering the number of times those people are going to keep casting their enums to ints (which is also throwing type safety out the window). If you type (int) about a dozen or so times, you’ve likely typed just about as much as that class; more if you just copy/paste it and change the type to the new enum. In that sense it’s almost more appropriate that lazy developers would implement this whenever using an enumeration for a dictionary key.