Monthly Archives: December 2010

Static polymorphism: possible or impossible?

It’s a well-known fact that there’s no such thing as a virtual static method in C#. So does this mean that “static polymorphism” is not possible?

Ha ha! Nope. I was toying around with this idea recently and came up with a funny little way of achieving… well, something like static polymorphism, anyway.

Here’s the basic idea. No, you can’t define a virtual static method. But what you can do is design an abstract generic base class with its type parameter constrained to only derived types. Like this:

public abstract class BaseClass<T> where T : BaseClass<T> { }

Huh? I bet you’re thinking. What does that accomplish? Right? I know you’re scratching your head! (OK, maybe you’ve thought of and/or encountered this before. Fine—but don’t spoil it for everyone else!)

With this odd-looking constraint, what we can do is give BaseClass<T> a static member of type T, while also defining virtual or abstract methods which T can or must override. Like this:

public abstract class BaseClass<T> where T : BaseClass<T>
{
    protected readonly static T s_instance;

    static BaseClass()
    {
        // This is the only way to instantiate a T object without resorting to a
        // where T : new() constraint, which would be pointlessly restricting.
        s_instance = (T)Activator.CreateInstance(typeof(T), true);
    }

    // This is a static method, but it's going to ACT like a abstract method...
    public static void DoSomething()
    {
        s_instance.DoSomethingInner();
    }

    // ...because THIS is an abstract method!
    protected abstract void DoSomethingInner();
}

Pretty sneaky, huh?

Now, in case you didn’t quite follow what’s going on there (it is admittedly a very weird design), allow me to explain. BaseClass<T> is abstract; this much we know already. But it includes a static member of type T; and this type must inherit from BaseClass<T>; so where we’ve defined the DoSomethingInner method as abstract, we’ve effectively “polymorphized” (is that a word? no… but it ought to be) the behavior of the static method DoSomething, since this is passing a call directly to our static T member.

Let’s make this a bit more concrete by actually defining a couple of derived classes.

public sealed class DerivedClassA : BaseClass<DerivedClassA>
{
    // There's really no reason to instantiate this class directly;
    // we only want it for our precious static polymorphism.
    private DerivedClassA()
    { }

    protected override void DoSomethingInner()
    {
        Console.WriteLine("Greetings from DerivedClassA!");
    }
}

public sealed class DerivedClassB : BaseClass<DerivedClassB>
{
    // Same comment as above.
    private DerivedClassB()
    { }

    protected override void DoSomethingInner()
    {
        Console.WriteLine("DerivedClassB says hello!");
    }
}

You can kind of see what I’m doing at this point, yes? But now for the real test: does it work?

class Program
{
    public static void Main(string[] args)
    {
        DerivedClassA.DoSomething();
        DerivedClassB.DoSomething();
    }
}

Output:

Greetings from DerivedClassA!
DerivedClassB says hello!

Hot dog! Static polymorphism (kind of)!

I know, I know. So cool, right? No? Bueller?

Advertisements

Thinking twice about .NET events in high-performance scenarios

Yesterday I asked a question on Stack Overflow about using .NET events in high-performance code. My question was, basically, whether it makes sense to do so, or if it’s appropriate to use some alternate strategy for providing “event-like” behavior that results in less GC pressure.

If you’re interested in the details of the question, you can always visit the above link. But in essence, my question stemmed from the realization that your typical event-based code involves:

  • A delegate most likely of type EventHandler<TEventArgs>, where TEventArgs derives from EventArgs
  • An object of the abovementioned TEventArgs type, which must be instantiated for every “event”

That last part is really the crux of my question. In a high-performance context, is it really the right thing to do to create a new object on every event, if events are happening extremely rapidly?

The voice of reason inevitably steps in to answer questions like this, and yesterday that came in the form of (among others—actually there were a few) the ever-reliable Hans Passant, an SO user I don’t happen to know personally but whom I’ve come to greatly respect for his consistently matter-of-fact and logical answers. He said:

[The TEventArgs] objects are always gen #0 objects. They don’t stick around long enough to ever get promoted. Both allocating and garbage collecting them is dirt cheap. This is just not a real problem, don’t chase that ghost.

100% sound, reasonable advice. But I chased the ghost anyway. And I’m posting this to share my findings with the world.

(The short answer, if you don’t feel like following me too far down this detail-laden road, is that Hans was right. It… barely… matters. But I still think the information I’m about to share is, at the very least, interesting.)

First of all, here’s what I did. I wrote a little demo program comprising the following pieces:

  1. An object that raises events at a ridiculously high rate (basically, as fast as the machine and the CLR can manage)
  2. A method that tracks GC collections and memory allocation while said object is doing its thing

Here’s the base type I used as a basis for each of the different “strategies” for raising events:

abstract class CrazyDataSource : IDisposable
{
    ManualResetEvent _stop;

    public CrazyDataSource()
    {
        _stop = new ManualResetEvent(false);
    }

    public void StartReceivingDataLikeCrazy()
    {
        var t = new Thread(ReceiveDataLikeCrazy);
        t.IsBackground = true;
        t.Start();
    }

    public void Dispose()
    {
        _stop.Set();
    }

    protected abstract void OnDataReceived(int data);

    private void ReceiveDataLikeCrazy()
    {
        int data = 0;
        while (!_stop.WaitOne(0))
        {
            OnDataReceived(data++);
        }
    }
}

As you can see, the above type calls OnDataReceived literally as fast as it possibly can (on a single thread). This is definitely an exaggerated scenario, as in virtually no cases will any real-world event be raised at this frequency. (I work at an algorithmic trading firm which trades thousands of products, whose software subscribes to real-time market data; and our market data definitely doesn’t come in that fast.) But sometimes taking an exaggerated approach is the best way to highlight real differences.

Now, to actually test out the performance difference between the various approaches to providing event-like behavior, I wrote three classes deriving from CrazyDataSource: one that raises events the “normal” way, one that raises events not matching the traditional EventHandler<TEventArgs> signature, and one that doesn’t raise .NET events at all and just uses a virtual method to signal the receipt of data (for example). And of course a little program to test the GC pressure exerted by each.

Now here’s the interesting part. Take a look at the output of an example run of said program:


Press Enter to start testing the 'conventional' event-based approach.
Press Esc any time to stop.

1000000 events raised; 321772 total memory used.
23 gen 0 collections
21 gen 1 collections
0 gen 2 collections

2000000 events raised; 264428 total memory used.
46 gen 0 collections
44 gen 1 collections
0 gen 2 collections

3000000 events raised; 207084 total memory used.
69 gen 0 collections
67 gen 1 collections
0 gen 2 collections

Finished. Cleaning up...
Done. Press Enter to continue.

Press Enter to start testing the 'unconventional' event-based approach.
Press Esc any time to stop.

1000000 events raised; 205660 total memory used.
0 gen 0 collections
0 gen 1 collections
0 gen 2 collections

2000000 events raised; 213852 total memory used.
0 gen 0 collections
0 gen 1 collections
0 gen 2 collections

3000000 events raised; 213852 total memory used.
0 gen 0 collections
0 gen 1 collections
0 gen 2 collections

Finished. Cleaning up...
Done. Press Enter to continue.

Press Enter to start testing the virtual method approach.
Press Esc any time to stop.

1000000 events raised; 205776 total memory used.
0 gen 0 collections
0 gen 1 collections
0 gen 2 collections

2000000 events raised; 213968 total memory used.
0 gen 0 collections
0 gen 1 collections
0 gen 2 collections

3000000 events raised; 213968 total memory used.
0 gen 0 collections
0 gen 1 collections
0 gen 2 collections

Finished. Press Enter to quit.

Now that, to me, is pretty interesting. The conventional event-based approach actually did result in not only plenty of garbage collections, but even generation 1 collections! This is contrary to what Hans had indicated, and it surprised me as well (how were those little objects making it all the way to gen #1?).

In contrast, using the “unconventional” event-based approach created seemingly no garbage at all. And neither did the virtual method approach. This makes sense; if you don’t instantiate objects, there isn’t going to be anything to collect. Still, the contrast is quite striking.

Now, before you get all excited and decide to forsake events forever, let me just state the obvious: this was a ridiculously unrealistic test. Any code you may deal with that raises a million events in like 1–2 seconds is likely to be… well, in desperate need of fixing. Or scrapping. So I am definitely not planning on digging through all my company’s code and refactoring the events out of everything.

But I am glad that I conducted this test, as it will inform the way I design high-performance components moving ahead into the future. In the context of real-time trading, where garbage collections are one’s worst enemy, it’s definitely good to know as much about where memory is being allocated in your code as possible, so that—should the need arise—at least you know where to go when it comes time to prune. (I’m not saying that stripping out events would be my first order of business, mind you. Not by a long shot.)

If only you were using .NET 4.0! Oh, wait a minute…

One thing I’ve always found strange is how users on Stack Overflow often say things like, “If you were using .NET Version X, you could do this”—when the feature is more or less trivial to implement yourself.

Take string.Join, for example. Before .NET 4.0, the System.String class had two static Join methods, both of which accepted a string[] parameter. This was a sometimes frustrating limitation of the string type; why do I need an array to join instead of any arbitrary IEnumerable<string>—or even IEnumerable<T>, for that matter?

It’s common to see the following sort of suggestion on SO:

List<string> names = new List<string> { "Homer", "Marge", "Bart", "Lisa", "Maggie" };

// If you're using .NET 4.0:
string joined = string.Join(", ", names);

// If you're using .NET 3.5 or older -- note that pesky ToArray call:
string joined = string.Join(", ", names.ToArray());

Now look, I realize this is pragmatic and totally reasonable. But there’s a reason they introduced new string.Join overloads in .NET 4.0; that reason is that copying a collection to an entirely new array is unnecessarily inefficient. Why should you have to copy your List<string>, LinkedList<string>, Queue<string>, etc. all to string[] arrays before being able to join them? You really shouldn’t. And yet, unless you’re on .NET 4.0, the suggestion is almost always to do precisely that.

If it were really complicated to write your own Join method accepting an IEnumerable<string>, I think I might be more sympathetic to this approach. But I work primarily in .NET 3.5, and it’s always kind of bothered me to have to call ToArray (or even Select(x => x.ToString()).ToArray()) in cases where I’m dealing with an IEnumerable<T>) everywhere I’m creating delimited strings from the contents of non-string[] collections. And the fact is that it’s not complicated at all. So why don’t we encourage people to just do it?

For the record, here’s a very simple version to illustrate what I’m talking about:

public static string Join(string separator, IEnumerable<string> values)
{
    if (values == null)
    {
        throw new ArgumentNullException("values");
    }

    separator = separator ?? "";

    var stringBuilder = new StringBuilder();
    bool pastFirstValue = false;

    foreach (string s in values)
    {
        if (pastFirstValue)
        {
            stringBuilder.Append(separator);
        }

        stringBuilder.Append(s);
        pastFirstValue = true;
    }

    return stringBuilder.ToString();
}

Now, the most obvious objection to this approach would have to be: Why bother? If a method like this is available in .NET 4.0, and you’re going to upgrade to .NET 4.0 at some point, why not just wait until that time and strip out those ToArray calls?

That’s fair, but my response would have to: Why wait? If you’re bothered by having to call ToArray, and an alternative solution is simple to implement yourself… I say just bite the bullet and do it.

What’s more, I recently learned that you can use the C# preprocessor to actually compile different code based on your target framework version. Which means that I can modify the above Join method as follows:

public static string Join(string separator, IEnumerable<string> values)
{
#if NET_FRAMEWORK_4
    // If we're on .NET 4.0, just use the built-in string.Join method.
    return string.Join(separator, values);

#else
    // Otherwise, let's use our own home-grown implementation.
    if (values == null)
    {
        throw new ArgumentNullException("values");
    }

    separator = separator ?? "";

    var stringBuilder = new StringBuilder();
    bool pastFirstValue = false;

    foreach (string s in values)
    {
        if (pastFirstValue)
        {
            stringBuilder.Append(separator);
        }

        stringBuilder.Append(s);
        pastFirstValue = true;
    }

    return stringBuilder.ToString();
#endif
}

This gives us a robust Join implementation which accepts an IEnumerable<string> parameter and will gracefully transition to the built-in string.Join method if and when the target framework version is changed to 4.0. What more could you ask for?

Personally, I’d like to see more of this sort of advice (if the version of the framework you’re using doesn’t include it, write it yourself) and less of the “If only you were on version X” variety out there.

My new Kindle, DOA :(

I was pretty darned excited when my wife got me a Kindle for Christmas—especially considering how skeptical she was (and is, I suppose) of the Kindle’s coolness (one of her first responses when I expressed interest in the Kindle or some other form of e-reader was: why would you want a Kindle instead of an iPad?)—I was excited, that is, until I turned it on and saw this:

Messed up Kindle

Messed up Kindle

Not cool, Kindle.

Fortunately, I contacted Amazon’s customer service (a big thank you to Fred, by the way, the poor guy they had working on Christmas Day) and should be receiving a replacement device in the mail as early as Tuesday next week, assuming the blizzards happening on the east coast right now don’t slow down the package too much.

My intention had originally been to discuss why I’m so excited for the Kindle (I don’t mean to sound like I have this incredible brand loyalty to Amazon; really, I would’ve been just as excited for a similar device from Barnes & Noble or Sony or any other reputable company that makes things like this… but the Kindle is certainly the most famous such offering) as opposed to, e.g., an iPad. I’m not against getting an iPad, mind you—in fact I’d say it’s likely that my wife and I will get one (or two?) for ourselves at some point in the next year or so, just because why not?—but I feel pretty strongly that devices like the Kindle are not irrelevant, that they do deserve a place among the various “nice-to-have” gadgets of our modern society, that they’re… well, basically just cool.

That was the plan. But reality has set in: I’m too tired. So I’m going to bed. Maybe I will write more about my Kindle when the replacement comes on Tuesday.

Anyway, I’m still excited, despite this temporary setback. I’m expecting big things from this little guy… or rather, the next little guy who’s on his way to take this little guy’s place.

In other news (and speaking of Christmas gifts that I wasn’t able to enjoy on Christmas), my wife also ordered me one of these bad boys:

Kinesis Advantage Pro

Kinesis Advantage Pro

It hasn’t arrived yet. But it will soon. Just look at that beauty and tell me you’re not jealous.

Rudolph the Red-Nosed Reindeer

Have you ever really thought about the lyrics to “Rudolph the Red-Nosed Reindeer”?

Rudolph, the red-nosed reindeer
had a very shiny nose.
And if you ever saw him,
you would even say it glows.

All of the other reindeer
used to laugh and call him names.
They never let poor Rudolph
join in any reindeer games.

Then one foggy Christmas Eve
Santa came to say:
“Rudolph with your nose so bright,
won’t you guide my sleigh tonight?”

Then all the reindeer loved him [emphasis mine]
as they shouted out with glee,
Rudolph the red-nosed reindeer,
you’ll go down in history!

What made all the other reindeer change their tune so suddenly? Were they just following Santa? Did Rudolph actually do anything to win them over? For that matter, why would Rudolph even want to be friends with the other reindeer after they “laughed and called him names” for seemingly no reason (other than unjustified prejudice based on his appearance which made him different from them)?

I’m not sure that I fully understand the message of this cherished holiday tune… I just find myself suddenly more skeptical of it than I used to be.

My oh-so-valuable time: how far is too far?

Most “regular” folks probably don’t realize that there are religions among software developers. Among these religions is one whose primary doctrine is “my (the developer’s) time is more valuable than the computer’s.”

Now, I’m not saying this is wrong. On first hearing it, one might even think of it as merely a statement of the obvious. But I’m not talking about common sense; I’m talking about religious conviction, the kind that enables devout individuals to stalwartly adhere to a principle even in circumstances where others might abandon it, or else make some sort of compromise.

I understand the value of my and other developers’ time just as well as the next guy/gal. But sometimes you do reach a point where enough is enough.

Consider, for example, this question from Stack Overflow. The user asking the question proposes the following code as a way of implementing the INotifyPropertyChanged interface without having to pass any parameters to a method call:

public virtual void RaisePropertyChanged()
{
    var frames = new System.Diagnostics.StackTrace();
    for (var i = 0; i < frames.FrameCount; i++)
    {
        var frame = frames.GetFrame(i).GetMethod() as MethodInfo;
        if (frame != null)
            if (frame.IsSpecialName && frame.Name.StartsWith("set_"))
            {
                RaisePropertyChanged(frame.Name.Substring(4));
                return;
            }
    }
    throw new InvalidOperationException("NotifyPropertyChanged() can only by invoked within a property setter.");
}

What is the above code doing? Can you even tell? In case you need some help making sense of it, let’s walk through it together.

Firstly, it’s creating a new StackTrace. That much is plain, right? But why is it doing that?

The idea is that the method above wants to figure out where it’s being called from, so that the caller doesn’t have to tell it. So, it looks at the stack trace, steps through its frames one by one, looks for a frame whose method has a name like “set_PropertyX” (by convention this will correspond to a .NET property setter), takes the portion of that string after the “set_” part, and finally raises the PropertyChanged event with that substring for the property name.

For a full example of all this in action, see my snippet on pastebin here.

The SO question is concerned primarily with performance. The actual title of the question is “Just how slow is this?” To me, the implication of this question is something like: Clearly this is a good thing, assuming it doesn’t kill performance too badly. So, how terrible is the performance? Because if it isn’t extremely terrible then I want to do it.

I’ve got nothing against the user who posted this question. Honestly, it’s a clever idea. Be that as it may, I can hardly believe someone would seriously consider actually doing this.

Just for the record, let’s look at our alternatives, using the code above and not using it.

Using RaisePropertyChanged

// Example of a property implemented using the above code
private string _name;
public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
        RaisePropertyChanged(); // Neat! I didn't have to type the property name!
    }
}

Not using RaisePropertyChanged

// Example of a property implemented the old-fashioned way
private string _name;
public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
        RaisePropertyChanged("Name"); // 6 more characters, yuck!
    }
}

Uhh… are you looking at that? Never mind performance for a moment; would you seriously prefer to create a stack trace and step through its frames looking for a method starting with the string “set_” than type 6 more characters?!

I know what you’re thinking: it’s not just six characters. It’s those six, another five here, another eight there, a dozen or so there… OK, sure. That’s a fair point. But let’s look at it from another angle. That RaisePropertyChanged method is fragile. It could be called from within a property setter that’s inlined by the JIT compiler; the only safeguard against that is to decorate your setter with the MethodImpl attribute and MethodImplOptions.NoInlining (at which point you’ve already suffered a net loss in terms of how much typing you need to do). Then consider that IsSpecialName check. Here’s what MSDN has to say about that property:

The SpecialName bit is set to flag members that are treated in a special way by some compilers (such as property accessors and operator overloading methods). [emphasis mine]

This is not a guaranteed, specified behavior. It’s a flag that’s used by some compilers. (Yes, I realize that Microsoft’s C# compiler is the de facto compiler that just about everybody uses; but that doesn’t invalidate this concern in principle.) So let’s say it’s not used by whatever 3rd party compiler you’re using for experimentation or whatever other perfectly legitimate reason you may have. Then it’s completely plausible that IsSpecialName might return false, and then… you’ll get an InvalidOperationException for calling RaisePropertyChanged in precisely the context in which it’s meant to be called!

That’s a pretty big “uh oh” in my book.

But you know what? This is all kind of unfair. If the question was originally about performance, then we really ought to be talking about performance. So let’s do that.

Based on my test, using RaisePropertyChanged costs about 2500 times what it costs to raise a PropertyChanged event the “old-fashioned” way, by passing the property’s name (as a string) directly to a method.

2500 times. To save yourself some typing.

To reiterate: I understand that yes, a developer’s time is more valuable than a computer’s time. But this?

This is why I mentioned religious conviction earlier. When you are willing to go this far just to save yourself a few seconds’ worth of typing, it’s a sign—in my mind, anyway—that your belief in this school of thought is approaching the realm of the religious.

An update: DelayedTextBox (better name suggestions welcome!)

Check it out, guys: a mere day after creating the TaoControls project on BitBucket, I’m here with a sweet new update: the DelayedTextBox control!

I developed this control to address what I felt was a pretty big hole in the functionality of the System.Windows.Forms.TextBox class (which happens to be the base class from which DelayedTextBox derives). As just about any developer familiar with Windows Forms knows, the TextBox (along with many other controls) has a TextChanged event, which gets raised immediately as soon as the text in the box is changed in any way—even by a single character.

I don’t know about you, but I’ve gotten pretty used to UIs that update dynamically as I’m typing (consider the “search as you type” feature that Google introduced not too long ago, for example). But at the same time, as a user I also demand that my UI remain responsive, always (in my opinion, an unresponsive UI has got to be among the top 3 most frustrating shortcomings of any software application featuring a GUI). The problem with the TextChanged event is that it’s indiscriminate, which makes it difficult to accommodate both of these requirements: dynamic updates + responsive UI.

For instance, the “Dashboard” application used by the traders at my company to monitor our overall trading activity includes a feature that allows the user to type in a symbol and immediately see the “book” (if any) where that symbol is being traded. Originally this was done by attaching a handler to the TextChanged event of the text box in question and performing the search in there.

I turns out this posed a problem: on relatively rare occasions, for reasons outside the scope of this post, the search would take… kind of a long time. Like, maybe 1–2 seconds. Which, from the user’s perspective—especially a trader’s perspective—is pretty disconcerting. If I was standing in the trading office at the time this happened, I would hear one of the traders curse and grow quickly panicked: “Call the exchange, the system’s frozen!”

Of course, after everything went back to normal within a second or two, things settled down quickly. But it struck me that reacting to every single keystroke (effectively) within a TextBox was, for our purposes, overkill. Really, I thought to myself, there’s no need to do that search until after the user’s finished typing.

We could always have done away with the FAYT (“find as you type”) functionality altogether and added a button labeled “Search,” of course. But this goes against one of the principles I mentioned earlier: having a UI that dynamically updates itself. So I set to work on a control that would offer the functionality I felt we really needed: a TextBox that raises an event only after a certain amount of time has elapsed.

This is basically what DelayedTextBox is: in addition to all of the properties and methods available to Textbox (which, by the way, still includes that old TextChanged event should you need it), it comes with two additional members: a DelayMilliseconds property, specifying how much time to “wait” after the user changes the text to raise an event; and a TextUpdated event, which gets raised after said time has elapsed.

Why not download it and give it a try? The downloadable .zip file includes an executable demo of all (2) controls in the library, so you can certainly give them a try before you decide whether or not you want to use them.

I’d include a screenshot, but it really looks just like a regular TextBox 😉

By the way, I’m totally open to suggestions for better names for this, SplitDataGridView, or any other controls I add in the future to TaoControls. If you’ve got an idea, let me know!

Here’s something that could maybe kinda be sort of useful…

I know I’ve said on more than one occasion that I was going to write about my “first open source project”; well, that hasn’t happened, partly because shortly after starting work on that project, I began losing steam fast. It quickly came to feel like an ill-conceived idea (for those of you who aren’t familiar with it—i.e., about 100% of you—it was a library of “thread-safe controls,” classes which wrapped Windows Forms controls and exposed identical functionality in a way that is thread-safe by using Control.Invoke and Control.BeginInvoke under the covers), and at this point I’m really not sure I even want it around anymore.

So with that behind me, I’d like to introduce a new open source project of mine: TaoControls. Unlike that other project I just talked about… which shall remain nameless even though it’s still definitely out there and I pretty much just explicitly named it mere sentences ago… this one should remain active for some time, as I continue developing in .NET and adding useful controls to it.

Right now the only control in the library is the SplitDataGridView, which fulfills a very specific need but is nonetheless (in my opinion) pretty cool. Here’s a screenshot to give you an idea what its purpose is:

Screenshot of SplitDataGridView control

Creating a dictionary with “enum-like” keys and strongly typed values

So here’s the idea I mentioned in my previous post.

A colleague of mine often uses (or at least he used to use) dictionaries to store settings, parameters, things like that. This isn’t altogether bad, but I personally am not a big fan of it. (I’ve talked to him about it, and his response has basically been: “Does it really matter?” To which I honestly have to respond, “Not really.”) The problem with this approach is probably best illustrated through code; so here’s an example of what I’m talking about:

// Note: hopefully it goes without saying that this is an oversimplified example,
// for illustration purposes only.
public enum CustomObjectSetting
{
    Name,
    Value
}

public class CustomObject
{
    Dictionary<CustomObjectSetting, object> _settings = new Dictionary<CustomObjectSetting, object>();

    public object GetSetting(CustomObjectSetting setting)
    {
        return _settings[setting];
    }

    public void ChangeSetting(CustomObjectSetting setting, object value)
    {
        _settings[setting] = value;
    }
}

Here’s why I basically hate this (though admittedly, the fact that I would hate it as opposed to just disliking it is really my own issue): while each setting might have a “correct” type, that type is enforced nowhere in the code itself (until the setting in question is used somewhere, where it is presumably downcast leading to a possible InvalidCastException). Any developers using this code need to just know what the type is for a particular setting.

This probably doesn’t seem like a big deal when you’re dealing with settings like, e.g., Name, which is presumably supposed to be a string. But it can happen (and does) that a setting is obviously numeric, but it’s unclear whether it’s supposed to be int, long, etc. Or that it seems like it should be numeric, but it’s actually an enum! (This actually happened once, where I assumed a setting with a name like “Size” (or something) was surely an int; but then it turned out it was an enum called something like QueueSize.)

These types of issues are resolved quickly through developer communication. But wouldn’t it be nice if there were some way to use a dictionary like this, with type safety? That is, if you could associate each enum value in some way with the type of the corresponding setting? After all, I get why my colleague likes to use dictionaries: they’re enumerable (without reflection), they’re easy to serialize, they’re fairly intuitive to use.1

Well, the reason I’m writing this post is to share with you that there is a way! In my opinion, it’s kind of a cool idea. Maybe you won’t agree with me; but anyway, here’s the idea. Instead of using a Dictionary<TKey, TValue> where TKey is an enum, define a new type that behaves like an enum, but with one crucial additional piece of information: the associated type.

Here’s a quick example of what I mean:

abstract class CustomField
{
	// Don't allow external code to inherit from this type.
	internal CustomField() { }
	
	// These readonly static fields will end up behaving essentially
	// like enum values.
	public static readonly CustomField<string> Name = new CustomField<string>();
	public static readonly CustomField<int> Value = new CustomField<int>();
}

sealed class CustomField<T> : CustomField
{
	// Don't allow external code to instantiate this type.
	internal CustomField() { }
}

class CustomDictionary
{
	// The keys of this internal dictionary are restricted to only certain values
	// (Name, Value), just like enum keys would be... but they will ALSO provide
	// type information.
	Dictionary<CustomField, object> _fields = new Dictionary<CustomField, object>();
	
	public void Set<T>(CustomField<T> key, T value)
	{
		// Since this is the only place where a value can be set...
		_fields[key] = value;
	}
	
	public T Get<T>(CustomField<T> key)
	{
		// ...this unboxing operation is safe (so long as the key exists)...
		return (T)_fields[key];
	}
	
	public bool TryGet<T>(CustomField<T> key, out T value)
	{
		object valueObject;
		if (_fields.TryGetValue(key, out valueObject))
		{
			// ...as is this.
			value = (T)valueObject;
			return true;
		}
		
		value = default(T);
		return false;
	}
}

In the above example, CustomField acts basically like an enum; but as you can see, its “values” (static fields) are actually instances of a derived generic class—CustomField<T>—so that each value is associated with a specific type.

This allows for the implementation of the CustomDictionary class, where there is a specific type associated with each key.

And voila, we have type safety with enum-like keys!

public class Program
{
	public static void Main()
	{
		var customDictionary = new CustomDictionary();
		customDictionary.Set(CustomField.Name, "Daniel");
		customDictionary.Set(CustomField.Value, 10);
		
		string name = customDictionary.Get(CustomField.Name);
		
		int value;
		customDictionary.TryGet(CustomField.Value, out value);
		
		Console.WriteLine("Name: {0}, Value: {1}", name, value);
	}
}

Output:


Name: Daniel, Value: 10

What do you think?

1: As I’ve already said, I don’t personally like this approach; but at least I understand it.

End of a semester

So I just finished my first semester of grad school, and it was a pretty great experience. Strangely, though, despite the fact that I’ve been using Ruby on Rails for the past several months for school, I haven’t really posted anything to this blog related to RoR.

I think this is probably because, being far from an expert on RoR—I still consider myself far more knowledgeable in .NET—I don’t have much interesting to say about it. It’s a great language/framework, and I definitely plan on using it in future projects (for me it is far superior to using PHP, at least sans framework, as I used to). I just have a long way to go in learning it inside & out.

With that said, in just a few minutes I’m going to write another post about an idea I had recently—in .NET, of course.