Variable names in C# (my 2¢)

I've gotten to the point that I've seen a lot of .Net source and a lot of different styles.  After a while it becomes pretty easy to know a lot about a particular coder from his style.  I'll look at one person's application source and think, “Hey, that's a VB 6 dev moving into C#“ and another where I'll think, “C++ guy who was drilled on Hungarian until he can't read code without it.“  When I say style, I'm not talking about higher level issues, like encapsulation, code reuse, and class hierarchies -- I'm just talking about the internal and private names we use in our own coding.  There's plenty of information on what your interfaces should look like externally (https://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconnetframeworkdesignguidelines.asp). But there's a diverse array of thinking on internal naming convention.

There are four issues that need to be addressed when choosing internal naming style, and each of these are going to be situational. You might end up going different ways on these issues based on project scale, complexity, and tools. I'll talk about part 1 today and the last 3 parts tomorrow.

  1. Should a variable name indicate what it does or what it is?
  2. How should a variable name indicate it's scope (member versus local versus static versus parameter names)?
  3. How descriptive should a variable name be (and when should you abbreviate)?
  4. How do you categorize (group) variables by name (particularly when using Intellisense)?

 

And before I start going on about any of these, I'll talk a little bit about my more firm style points. Again, these aren't “official“ rules, these are just peronal rules I've developed while writing (and reading!) lots of managed code.

  • Camel case all private, internal, and locally scoped variables. No underscores!
    • Examples
      • FOO ---> foo
      • foo_bar --->fooBar
      • Hi_There ---> hiThere
  • Avoid bunching capital letters
    • Examples
      • MDXTest ---> mdxTest
      • OPEC ----> opec
      • parsedHTML ----> parsedHtml
    • Grey Areas (in these cases, I usually opt to find a better name for the variable)
      • hiIAmAVariable ----> hiIAmAVariable (ok, but a little “loud”) hiIamAvariable (follows rule, but hard to read, I would avoid this)
  • Avoid number names
    • There are almost always better ways to describe by function
    • Examples
      • run1, run2 ---> runInitialize, runValidate

Should a variable name indicate what it does or what it is?

The first question addresses the most general aspect of the variable name: does it indicate function or type. Now the rule for external api's is that a name should always explain function. The idea that type-safing and meta data provides enough information about the variable to indicate it's usage. However, there might be cases (particularly internally) where you may be introducing ambiguity by not specifying type. The easiest scenario would be when using unsafe data. In this case it may be important to specify the type of a void pointer (if known). 

Your tools may also determine your naming. I'm fairly spoiled in that I use the Visual Studio IDE almost exclusively. If I ever need to know the type of something quickly, I can float my mouse cursor over it and I know instantly what it is. However, there are plenty of teams that don't use fancy text editors and some that use plain old notepad (I still use it myself from time to time). Lets say that same notepad.exe user is dealing with a several highly abstract DOM objects like those used to represent XML documents. In this case, it may be helpful to distinguish between an XmlNode object and a string containing the XML data. In these cases, I'll usually just spell out the type, so that XmlNode might be myHeaderNode and the String would be myHeaderString.

A final case for using type names might be when using a lot of polymorphism and casting. Take the following (somewhat nonsensical) example:

private class MySuperClass { }
private class MyHappySubClass : MySuperClass{ }
private class MySadSubClass : MySuperClass { }

public void SomeFunction(MySuperClass thing) {

...determine that thing is of type MySadSubClass

MySadSubClass sadThing = (MySadSubClass) thing;

}

In this example, we're casting an instance of MySadSubClass to a local MySadSubClass variable to make it easier to work with. There are some times when you'll want to determine the actual type of an incoming object at runtime and do some specific operation on it. Managed code makes it easy to reflect the type of an instance. In this case, we want to emphasize that “sadThing” is the same instance as “thing”, but we also want to indicate its type to avoid confusion when operating on the specific functionality defined by the subclass. Again, this is a pretty forced example -- there are plenty of reasons not to try to reflect the type of an instance for specific use at runtime, but if the situation is unavoidable, this naming convention can help sort things out.

To be continued....