Framework Design Guidelines on Names of Generic Type Parameters


Framework Design Guidelines on Names of Generic Type Parameters


Continuing in the series of discussing topics from the Framework Design Guidelines… The last post generated some good discussion on generic type parameter naming I though I’d include this. 


 


 


Names of Generic Type Parameters


Generics are a major new feature of the .NET Framework 2.0. The feature


introduces a new kind of identifier called type parameter. The following


guidelines describe naming conventions related to naming such type


parameters.


 


DO name generic type parameters with descriptive names, unless a


single-letter name is completely self-explanatory and a descriptive


name would not add value.


public interface ISessionChannel<TSession>{ … }


public delegate TOutput Converter<TInput,TOutput>(TInput from);


public class List<T> { … }


 


CONSIDER using T as the type parameter name for types with one


single-letter type parameter.


public int IComparer<T>{ … }


public delegate bool Predicate<T>(T item);


public struct Nullable<T>where T:struct { … }


 


DO prefix descriptive type parameter names with T.


public interface ISessionChannel<TSession> where TSession :


ISession


{


   TSession Session { get; }


}


 


CONSIDER indicating constraints placed on a type parameter in the


name of the parameter.


For example, a parameter constrained to ISession might be called


TSession.


 


What do you think?  Have you started using generics heavily enough yet to form a solid opinion on this? 

Comments (16)

  1. barrkel says:

    I think these guidelines are pretty bang-on. Converter<,> and things like it would have been a lot harder to understand with just T,U etc.

    The most complex generic method I’ve written in production code so far has just three generic type parameters; these parameter guidelines help make that scenario work well in the IDE.

  2. I definitely agree with the recommendations of when to use a descriptive name and when not to; I’ve written generic types both ways and find that it represents a good compromise between comprehensibility and excessive typing.

    I still wish the "T" had been introduced as a suffix rather than a prefix, although I can’t give any concrete justifications for that. I’m getting used to seeing things like TKey and TValue, but somehow KeyT and ValueT just seem much more "right".

    Other than that nit, I think the guidelines are great 🙂

  3. Btw, do you think you might consider telling the authors of the LINQ spec to consider actually following these guidelines? I followed most of the LINQ paper but the bit introducing all the generic methods went completely over my head simply because I couldn’t figure out the intended meanings of more than one or two of the generic parameter types…

    Perhaps a useful guideline would be that if you’re considering using any single letter *other* than T you should probably use a descriptive name instead 😉

  4. I think it would be best to use the Type postfix, just like with the guidelines for Collection types (appending the word Collection to the type, like "NameValueCollection"). I can say for myself that I use this guideline with many other types, like DataSets (such as "CustomersDataSet").

    I would prefer to see KeyType and ValueType, that feel more natural, when considering the rest of the framework. TKey and TValue seem like you guys are trying to be backwards compatible with the C++ way of coding (like IMyInterface), rather than continuing along the standards in C# that you have created yourselves.

    IMHO, it would seem more appropriate to see the following instead of the way you suggest:

    public interface ISessionChannel<SessionType> where SessionType : ISession

    {

    . . SessionType Session { get; }

    }

  5. Carl says:

    This seems like a regression to the old CMyClass naming convention. Framework naming conventions have avoided this with the exception of the IMyInterface convention. I’d vote for the KeyType/ValueType style naming mentioned by Omer. It seems in line with the rest of the framework, staying away from abbreviations and sticking with real words.

  6. KeyType, ValueType etc sound nice until you actually try to use them.

    The problem is that when you read code like "SessionType Session { get; }" (from Omer’s example above), the normal meaning of this in C# code is "Session is a property whose value contains a Session Type" (my natural reaction would be to expect something like "enum SessionType {Cookies, UrlMangling}" or something – by normal C# conventions "SessionType" means "a type of session").

    In this case that’s not what it means at all: it means "Session is a property whose value contains whatever type is defined as the Session Type for this particular instantiation of the generic type". In other words, Session isn’t a "type of session", it *is* a session.

    In this case trying to follow the "C# way" actually gets more confusing because it results in an ambiguity with the already-existing C# way.

    I agree that it’s more C-sharpey to use a suffix rather than a prefix, but "Type" doesn’t work as that suffix, and I’m *very* glad they didn’t succumb to the pressure to recommend that.

    (I have actually adopted the TKey/TValue naming convention in my code even though I think KeyT is better, because there’s value in being consistent with everyone else. But if they’d recommended KeyType/ValueType I’d have completely ignored the recommendation and gone my own way, because the recommendation would have led to writing code I couldn’t understand myself)

  7. Kevin Dente says:

    I’m with Omer. It seems to be another case of Hungarian sneaking in.

  8. Kyralessa says:

    I have a more generic (heh) question: What’s with all the "Do" and "Do not" stuff in MSDN2?

    Take here, for instance:

    http://msdn2.microsoft.com/en-us/library/ms229043(en-US,VS.80).aspx

    Do capitalize both characters of two-character acronyms…

    Do capitalize only the first character of acronyms with three or more characters…

    Do not capitalize any of the characters of any acronyms…at the beginning of a camel-cased identifier…

    Do not capitalize each word in so-called closed-form compound words…

    And so forth.

    What I find is that all those "Do" and "Do not"s run together. Why not just say "Capitalize" instead of "Do capitalize"?

  9. Stuart has a point – SessionType really does look like ‘instance of an object/enum/etc. that indicates the type of session’, but until I can find something better (‘SessionTypeParameter’ and ‘SessionTypeParam’ are just too long), I’ll be sticking to the ‘Type’ suffix.

  10. Anders Borum says:

    Hello Brad

    This article could use an HTML refactoring. Headlines are on top of eachother and the changing font sizes in content makes for a hard reading experience 🙂

    That said, I would like to see more on design from you (and your team). Always interesting to visit your blog.

  11. Andrew Webb says:

    These guidelines are a wonderful thing and a major step forward for generics. To think we went into the .NET 2.0 dev phase with the old C++ T, U, V, I, J, K throwbacks! Their presence blighted the otherwise beautiful construction that was/is .NET generics.

    However, I would have gone further and said that descriptive names should always be used. The guidelines say to use a descriptive name "unless a single-letter name is completely self-explanatory". The trouble is that when writing List<T> (say) its author considers T to be "completely self-explanatory". The same goes for the authors of (for example) the delegates Action<T>, Predicate<T> and Comparison<T>, all working in isolation on their types.

    Now the user comes to use all these things together in their code… oh la la… the letter T is bandied about all over the place until your eyes start to swim. "completely self-explanatory" goes out the window.

    But what the hey?! The guidelines are a massive improvement, and not always inisting on descriptive names was probably a pragmatic, politically astute move. What was amazing about this whole business was the level of public consultation via Ladybug, and the fact that Microsoft completely changed its mind on this issue. That degree of flexibility is impressive.

  12. Dave R. says:

    I followed the arguments over on the feedback site during the beta and the resulting recommendation shows that Microsoft really listened to the users.

    The compromise approach gives more readability than the old C++ alphabet-soup, but keeps it concise and immediately recognisable. I think that generics are pervasive enough to warrant the prefix approach, ranking alongside the interface guidelines as a special case.

    I’ve been writing generics code since the beta timeframe and the above recommendation enhances readability without being overly restrictive.

  13. Daniel Petersson says:

    Perhaps a little off topic, but how should collections, that are based on generics, be exposed to an api?

    Ex "Short":

    class Foo

    {

    public ReadonlyCollection<Bar> Bars

    {

    get{ … }

    }

    }

    Ex "Long":

    class BarCollection

    : ReadonlyCollection<Bar>

    {

    }

    class Foo

    {

    public BarCollection Bars

    {

    get{ … }

    }

    }

    I really prefer the first version but perhaps the second easier to read??? What do you think?

  14. cowboy matt says:

    Another vote for Omer. Looks like someone is trying to sneak hungarian in. Personally I like hungarian, but, more, I prefer the standards be consistent.

  15. Andrew Webb says:

    Personally I would have prefered suffix T, as in KeyT and ValueT. However, Microsoft had their reasons. Just wish I could remember what they were! 🙂

    As regards "Type" as a suffix… While I have sympathy with this, and for a while suggested it as the solution, it does lead to problems. Stuart has already highlighted some of them above.

    It was Krzysztof Cwalina on his blog entry here:-

    http://blogs.msdn.com/kcwalina/archive/2004/11/04/252473.aspx

    who pointed out another. A generic Dictionary class takes parameters for the Key type and the Value type. If we used the "Type" suffix system, you end up with "ValueType"… which clashes with the name of an existing class in the base class library.