Naming generic type parameters…


There’s been quite a discussion going on on the MSDN feedback site over the naming of generic type parameters.


If you look at the definition of the generic collections classes, you’ll see things like:


List<T>
Dictionary<K, V>


What’s up with those T’s, K’s, and V’s?


If you look at our beta1 library design guidelines (can’t find a published link right now) that suggests that you use single-character names for type parameters rather than longer, more descriptive names. But those guidelines weren’t always there. In fact, before we had them, you might see a class like:


class Dictionary<Key, Value>
{}


which seems reasonable enough. But one day, you’re browsing code, and you look at a method:


public void Process(Key k)
{
    // code here…
}


What’s Key? It looks like it’s a type, and unless you know that there’s a type parameter named “Key“, you’re likely to be confused for a while. We therefore decided to use the single-character naming approach, and my experience is that it’s worked pretty well.


When you’re working on a generic class, you normally have a small number of generic type parameters, and therefore it’s not that hard to keep them straight. When you’re using them, C# intellisense is nice enough to give you a description for the type parameter so you remember what it is.


That is, it’s nice enough to do that if you remember to *write* the description using the <typeparam> tag. The IDE will add this tag automatically when you type the /// before your generic class definition.


Unfortunately, the beta1 drop doesn’t have these descriptions for the built-in collection classes, so you don’t get any help right now if you type “List<“. We’ll be fixing that.

Comments (31)

  1. drebin says:

    This really struck me as odd too. I disagree with the T, K, V naming convention.

    Yes, it will look like a data type, so why not just use a descriptive name? Perhaps:

    class Dictionary<GEN_A, GEN_B, GEN_C>

    {

    public void Process(GEN_A genValue, GEN_C genObject)

    {

    // code here…

    }

    }

    If that were the "standard", it would be clear that when you are working with a GEN_ "data type", it’s a generic.

  2. Voytek says:

    Hmm…

    Then maybe we should write:

    public class CLASS_Button { … }

    or

    public struct STRUCT_Point { … }

    or

    public interface INTERFACE_IComparable…

    or

    public void METHOD_Process() { … }

    Prefixing rather has no sense…

    In my opinion "single letter" is OK 🙂

  3. sebmol says:

    I think the single letter convention is great. That’s already the standard for most of all C++ template classes. If a strong, working convention already exists, why not embrace that?

  4. Click on the word "Key".

    Press F12.

    Know. 🙂

  5. Mark Ayers says:

    "When you’re using them, C# intellisense…."

    Remember C# doesn’t give me intellisense the IDE does. This does nothing for Don when he is using emacs, [if he still is].

  6. drebin says:

    Voytek, generics are clearly a different kind of thing should be handled differently.

    but Sebmol, good point…

  7. Mark Mullin says:

    I think I’m starting to miss Hungarian notation

    The single letter convention works, but it makes everything read like a math equation – very dense, you have to go slowly, and a single (easily made) misassumption can kill ya

  8. Mark,

    This not a c# issue. It doesn’t go in the spec. It’s just a recommendation from Microsoft, who happen to own IntelliSense. 😉

    If you don’t use the VS IDE, just use your own notation. I think I’ll stick to ‘long’ names because everyone I know uses VS and I think they’re just better. 🙂

  9. Luc Cluitmans says:

    I wrote this already in other words in the feedback thread, by take on this issue is as follows.

    I agree with the single letter type names, and Eric’s argument that these names make them more recognizable is the best argument indeed.

    What some people seem to forget is that there are two roles for users of generic classes: the ‘Writer’: the programmer who is writing (and documenting) the class and the ‘Consumer’; the programmer who uses the instanced classes.

    For these two roles, the way the template type names (‘T’, ‘K’, ‘V’, etc.) are viewed is different. The discussion may become more clear if you look at it from a distance and see that the goals of these roles are not the same.

    The ‘writer’ will actually use these type names. He will like a clear way to distinguish those types from anything else he is writing, and using single-letter names is a great way to achieve that goal.

    For the ‘consumer’ the documentation that comes with the class is more relevant than the actual source (at least: that should be the case). Here I consider ‘documentation’ to be both the actual documentation (e.g. generated from XML comments) and the public API of the type. I can imagine that people who look at it from this way prefer to see more descriptive names.

    I think that the <typeparam> tag mentioned by Eric (this is the first time I hear about it) goes a long way in bridging the gap between these two views. Of course, this assumes access to an IDE that will actually show those tags in Intellisense, and won’t help people who prefer to do their coding in Edlin…

  10. Nikolay Botev says:

    I had seen the MSDN discussion and the first thing I thought of when reading Eric’s post was "prefixes"!

    So, I’d like to elaborate on that because the first two comments but both fail in two different ways (no offense intended).

    The first post proposes using a prefix in ALL CAPS and separated with an underscores – both obsolete conventions from the C/C++ times.

    The second post is a little more interesting – it successfully refutes the first post by examples of what names would look like if we used this sort of prefixes all over the place, yet it misses out on an important point. If you look at this line:

    public interface INTERFACE_IComparable

    Well, here both the "I" in "IComparable" and "INTERFACE_" are both prefixes. So the"INTERFACE_" part is actually redundant since C# already uses prefixes for interface names by convention.

    So, my proposition is: how about a single letter prefix for generics types? Then the Dictionary example could look like:

    Dictionary<TKey, TValue>

    and looking at the method declaration:

    public void Process(TKey k)

    is no longer confusing.

    Finally, I would like to add – I agree with Mark on the IDE vs. language point and this is in fact the only reason why it would make sense to discuss this issue: IDE users don’t really have a problem.

  11. Nikolay Botev says:

    I just noticed that the proposed solution of the issue ticket on the msdn site (the first link in the post) is the same as my idea above with the exception that T is added as a suffix instead of a prefix to the name:

    <blockquote>

    Use mnemonic names for parameterized types throughout the documentation, instead of meaningless single letters. To be more specific, use the descriptive-name-with-suffix-T convention (e.g. ItemT, KeyT, ValueT, FromT).</blockquote>

  12. damien morton says:

    If the IDE can succesfully differentiate generic placeholders from other names, then theres no probelm whatsoever.

    Failing that, I suggest ALL CAPS for the gernic placeholders.

    Dictionary<KEY,VALUE>

    public void Process(KEY k)

  13. Stuart says:

    I’ll add my vote for using T either as a prefix (TKey, like IComparable) or a suffix (KeyT) for generic type parameters. Either is better than the single-character names. Suffixes read more naturally if you mentally expand the T to "type" – "key type" etc. However, hat logic would also apply to IComparable, and there’s value in consistency too. If pushed, I’d go for suffixes; it’s just a gut feeling, but I think the distinction from regular types would be clearer to me that way.

    I agree with a poster above who pointed out that a language-level rather than IDE-level solution is appropriate here. I love what the IDE does for me (VS.NET is the first IDE to make me feel that way, incidentally) but I’d hate to be dependent on it for something like this. We might as well start naming all our variables v1, v2, v3 and rely on the doc-comments and mouseovers to know what all of them are…

  14. Stuart says:

    Typo: "hat logic" – should be "that logic" of course. "Hat logic" sounds like what the teacher from South Park uses…

  15. Jerry Pisk says:

    T stands for Template, from C++ templates. So .Net version should use G, for generics as a generic type prefix.

    And yes, generics are the same as C++ templates, they’re just not called templates. And C++ templates can actually do more than generics (template parameters can be just that, parameters, they don’t have to be types).

  16. Jon Galloway says:

    I agree Mark on this one. "EventArgs e" always bugged me, too. Doesn’t feel like a high level language naming convention at all. A single letter has no meaning (other than perhaps I or A…). We’ve got GB’s to burn, we can spare a few extra bytes here and there.

  17. Quaid says:

    Jerry Pisk: "T stands for Template"

    T stands for Type, shurely?

    This ‘single letter disambiguates type parameters from types’ argument makes no sense to me. In the generic code, the template parameter stands for a type, so it *should* look like a type.

    Whenever I write C++ template classes I use descriptive names like TKey or KeyType, which describe the kind of type, as well as flagging up that it’s a type.

    Most of the time, programmers will be using a generic type, not writing it.

    A descriptive type parameter name is important.

  18. Darren Oakey says:

    ok –

    a) ALL prefix-based conventions are bad. We learnt the painful way with hungarian, lets not make the same mistake again. For example, even the very poor IBlah convention – how many times have you replaced a concrete class with an interface? Should the consumer of your class care? They call a factory, get an object back – it’s none of their business whether they are dealing with a class or an interface! – just lots of rewriting to do if you wanna stick to a poor convention. I’ve also seen databases with every Table prefixed T, and every view prefixed V. Let’s wake up and remember our sanity!

    b) people are ignoring what Omer has said – but it’s quite right – if you really "want to know" – you can _easily_ find out…

    however – on that…

    c) every time you USE a template, you will see code like

    > Blah<int, string> x = new Blah(10, "hello");

    you WON’T see the template parameter names. The only place you will see template parameters is in the template code itself. You _should_ be aware that you are looking at a templated class, and the parameters when you open the class – they are at the top of the screen! but really, it _shouldn’t_ really matter. If you see

    > void Add( Blah theKeyToAdd ) {_internalList.Add( theKeyToAdd );

    you understand the intent of the function, and if you need to fix it, you can – you DON’T need to know immediately that it is a templated or a concrete type…

    d) If you DO really want to know immediately, there is a perfect an obvious solution readily apparent – colour syntax highlighting – template parameters appear in a different colour – easy – obvious, and doesn’t require developers to have followed one of many "standard" conventions.

    e) but the most important reason that template parameters _must_ be named properly is always for the developer. You’ve made your ClassCopier<A,B> function. You made it years ago. You have to put in a new CopyAndLog function on it.. hmmm… now is A the source or the destination? do we copy from A into B? or do we take B and store it in A? who knows? Now, suppose the function was named ClassCopier<destinationType, sourceType>. Gee… now it’s easy!

    We should be writing code for readability, reliability and maintainability, and meaningless template paramaters fail on all counts. The one tiny advantage (that is that they are immediately recognizable as template parameters) is easily replaced by a better cue (ie colour), should be obvious from the name of the template parameter anyway, and finally, IS NOT ACTUALLY IMPORTANT for the reader to know, when they are first reading through the code!

  19. It will be interesting to see what you guys do with the feedback now. It’s apparent that you’ve had a discussion internally and decided to make those changes toward T, K, V. You even state that you find it works well. So we know your opinion.

    However, the comments at the feedback center are overwhelmingly in favor of more descriptive names. Now you know our opinion.

    Will you be able to change your mind based on this feedback, or is this whole thing all for show?

    Don’t get me wrong, I really like to see Microsoft opening up a bit, the blogs, Channel9, all that stuff. I also understand that the people doing all the hard work will always have a disproportionate say in those decisions (and rightly so! not everything has to be democratic). But the suggestion was put up there on your own feedback center and publicised by yourself, and now a majority of people who took the time to provide feedback want more decriptive names.

    The ball is in your camp.

    For the tally, my lowly opinion on the matter is that T is fine for collections, K and V for dictionary collections is stretching it a bit, and for everything else it should be plain un-adorned descriptive names. That means List<T>, Dictionary<Key, Value> (or maybe Dictionary<K, V>) and Convert<To, From> for example. My reasoning is that T for collections is already well-established as a convention in C++ so it’s ok, but in general things should be self-documenting as much as possible; just as you wouldn’t have Console.Write(string m), you shouldn’t have single-letter generic parameters.

    In any case, thanks for listening!

  20. Voytek says:

    Darren Oakey, You have right… Who cares how You name template parametes if none will browse code. Everyone before use your templated "component" will read documentation and seethat K is for entry key and Value is for Entry value.

    Problem is not with using this class like black box but "revisiting" code and making changes by someone else thant author.

    You can write classes with nice interface like:

    class Dictionary<K, V> { V Get(K key) {} }

    an intrnally use variables and members like "a", "u", "uuu", "z324" why not!?

    But in this case readability will suffer…

    When class is longer than one screen looking at implmentation is harder to see ehat is member, template parameter, od method parameter if free-coding-convention is used 🙂

    And not "ALL prefix-based conventions are bad", but generaly it is true 😉

  21. Mario Goebbels says:

    I’m fine with the single letter parameters, but it’d be nice if you also set up some official guidelines for the naming, like T is type, K is key and V is value currently. I can’t think of more yet, since I’m happy with T,K and V in my own types.

  22. David Bossert says:

    I’m willing to go with whatever most people are using, but I just want to say that it makes me sad that .NET programmer are even considering prefixes. In a perfect world, people who use anything even vaguely Hungarian, including m_ on private fields, would be shot in the face. I just wish people would realize the the problem isn’t what we name the parameters; the problem is the horrid angle-bracket syntax we’re forced to use.

  23. Gavin Greig says:

    I’m with Stuart and Quaid on this one. My preference would be a "Type" suffix that spells it out (e.g. KeyType).

    Having used templates quite a bit in C++, I’m not in favour of the single letter approach, no matter how accepted it may be :-). I find that declarations that use the type parameter can be particularly difficult to read correctly first time.

    I’m not generally in favour of the Hungarian-style approach to naming variables, but I think there are a few cases where some meta-information in the variable names is useful. Identifying types as being types is one of those cases.

  24. Stuart says:

    It occurred to me that there are at least two precedents in the .NET framework for a suffix-based convention.

    IOException, SocketException, DataException, …

    SerializableAttribute, IndexerNameAttribute, …

    (the latter convention is even supported at the language level)

    I think both of these examples are more relevant than the "IFoo" convention because they are almost never (as far as I’ve seen, anyway) criticized as "hungarian-like". They’re so obvious and understandable that nobody thinks of them in that way. So not all suffix-based conventions are bad.

    My reason for preferring KeyT to KeyType is that if you read "KeyType k = something" it sounds like k is a "type of key" (enum KeyType {Brass, Gold, Silver, StainlessSteel}?), when in fact it actually *is* a "key". We want something that reads as naturally as "Key k = something" – where it’s clear that k is a Key – but still makes it clear that the type of "k" is something special. Sorry if this paragraph is a bit hard to follow – I can’t think of a way to express it more clearly. Talking about types of types clearly is hard 🙂

  25. Mark Mullin says:

    I’d strongly agree with Gavin’s last comment. He’s hit the nail on the head – the IDE isn’t the only place one sees code, and as the complexity of OO languages rises, it’s important to see both syntactic (meta information) and semantic (just what the heck is X, anyway) information in one glance.

    I’m no huge fan of hungarian notation, on the other hand I think I’d rather be shot once in the face for using m_ than repeatedly in the foot for not. Consider the following…

    In a large program, you have a number of classes that expose internal member variables as properties, some for public consumption and some for private, and many member variables aren’t exposed at all. Hence

    m_myVar is a direct reference to an internal member variable

    myVar is a private property reference to an internal member variable

    MyVar is a public property reference to an internal member variable

    I see many cases like this, as properties can often incorporate state logic for dealing with member variables. For example, in 3D classes I use, internal points may be stored as null, but if the property representing these points is requested, SFVec3f(0,0,0) will be returned. This is also the case with more complex structures like matrices, it’s better to represent null as an uninitialized identity matrix than it is to set the silly thing up and keep it around.