I want better aliases in C#. To be honest I miss this feature since .NET 2.0. I mean, it’s not a problem of .NET, but merely a problem of the C# language itself. To me, aliasing is a very important language feature. In my opinion, it’s one of the three most undervalued language features: macros, aliases and comments.

Global Type Alias

First off, let me define what a global alias is for me. A global type alias is best described with the current aliasing feature in C#:

using System;
using Dump = System.Diagnostics.Debug;

public class Writer {
  public Writer() {
    Dump.WriteLine("Writer!");
  }
}

The second line is a using alias. It’s quite handy to avoid name clashes in your source file. And that’s the downside (for me) as well. In C#, it’s only possible to define type aliases on source code file level. While it’s perfectly ok for resolving name clashes, it’s yet not enough for me in terms of sensible alias usage.

From my perspective, a broader - even declarable - scope of a type alias would be very helpful. As a starting point, I’ll define a “global” type alias as an alias valid on assembly level.

Global type aliasing can be very helpful. I miss it most for generic types, since they’re not only tend to be verbose but can be misleading as well. I mean, how often did you ask your inner self the famous three letters (WTF?) when seeing something like ServiceResponse<Dictionary<long, List<string>>>? Yes, sure you can alias it with using RoadServiceResponse = ServiceResponse<Dictionary<long, List<string>>>.

Now would you want to define this alias in every single file where you process this mighty response object? Surely not. Redundancy is boring. However, if you’re using C#, you just have to. A widely scoped type alias is surely possible if you were using VB.NET with its Imports feature.

Alias Open Types

Lengthy and complicated naming is one reason. A second, even more demanding reason for global type aliases are the use of generic implementations or generic interface definitions. It may sound weird in first instance, so let’s see an example here:

/* Assembly A: My 'cool' API :-) */
using System;
using System.Collections.Generic;

public interface IMetaData<T> {
  string Id { get; }
  T Data { get; }
}

public interface IRelationMap<T, TKey, TValue> 
  : IDictionary<TKey, TValue> {
  TValue GetRelated(T obj, TKey key);
  T RelateTo<T>(TKey key);
}

public interface IMetaInfo<TSource, TData> {
  IRelationMap<TSource, string, IMetaData<TData>> Properties { get; }
  TSource Object { get; }
  int ChannelId { get; }
}

A little unreadable for the generic types, but quite straight forward so far. Let’s implement IMetaInfo:

/* Assembly B: My 'cool' Service :-) */
public class TextMetaInfo<T> 
  : IMetaInfo<T, string> {
  public IRelationMap<T, string, IMetaData<string>> Properties { get; set; }
  public T Object { get; set; }
  public int ChannelId { get; set; }
}

Doesn’t this look weird? Wouldn’t this one be a little more readable:

using System;
using System.Collections.Generic;

using IMetaMap<T> = IRelationMap<T, IDictionary<string, IMetaData<string>>;

public class TextMetaInfo<T> 
  : IMetaInfo<T, string> {
  public IMetaMap<T> Properties { get; set; }
  public T Object { get; set; }
  public int ChannelId { get; set; }
}

Sad enough that above code won’t compile. C# only accepts aliases for closed types.

Yeah, you might think now that this is just nitpicking, since you surely might just derive to have naming done right:

public interface IMetaMap<T> : IRelationMap<T, IDictionary<string, IMetaData<string>> {}

Sorry to disappoint you here. “Fixing naming” by subclassing is just wrong. Despite of the bad smell you simply made it even worse since you now made it a lot harder to implement IMetaInfo<T, string>. If you were the consumer of Assembly A without any source code access, you lost anyway. If you actually have access to the sources of Assembly A, you end up in deciding whether to change the type signature of IMetaInfo<TSource, TData> just for naming. In consequence, other implementors need to change their implementations. Even callers need to recompile. For the sake of readability?

Sorry, C#. You are doing a good job being a multi-paradigm (yet OO-colored) language. However, when it comes to aliasing, you could do better.


(c) 2000-2012 ilker.de - Creative Computing.

For any case of inquiry regarding this document, you can always contact the website owner.