29

Back in the old days, we did Hungarian notation. That's now considered passé, and for the most part I don't use it anymore, but I still find use for the m_ prefix to indicate member fields.

For me, if I'm reading through someone else's code, and I see this:

count = 3;

I assume that count is a variable local to that function and I'm doing something that will be used elsewhere in the function; if I see this:

m_count = 3;

I immediately realize that I'm updating the state of the object.

The Microsoft style guidelines say that's the wrong way to do things. I'm supposed to name my non-public fields exactly like temporary variables defined within the function. No m_, not even a simple underscore.

Yes, we can define our own coding style, but then I have to wrestle with various static code analysis tools, to convince them that our way of doing things is OK.

I'm happy to change to the Microsoft style, but I'd kind of like to know why things are the way they are.

Why is it now considered bad to be able to tell whether a variable is function local or a member?

P.S. This is very similar to What is the regarded current best practises regarding the “this” keyword in front of field and methods in c#?, but I'm asking about m_ not this.

P.P.S. Also see Why did Microsoft make parameters, local variables and private fields have the same name naming convention?

8 Answers8

25

When they were working on the API for Windows, Microsoft recommended the use of Hungarian Notation, using 'm_', as well as 'i', 'sz', etc. At the time, this was useful because the IDE wasn't robust enough to show this information to you.

C#, on the other hand, has a very robust IDE from the outset.

So they made the recommendation in Microsoft's Naming Guidelines for C# for public static or protected fields:

✓ DO use PascalCasing in field names.
✓ DO name fields using a noun, noun phrase, or adjective.
X DO NOT use a prefix for field names.

Now that you can hover over it with your mouse, or press CTRL+K+W, and get all the information about the member, Microsoft came to the determination that prefixes are bad form; they are a manual solution to an already solved problem.

Private fields are specifically excluded from the guidelines, but Microsoft seems to have come to the conclusion that this is the case even for private fields going forward internally, which you can see if you point Resharper at .NET 4.5 or .NET Core.

Use your tools, don't do it manually.

Kevin Fee
  • 2,847
16

C# doesn't have any global variables, so that leaves only local variables and class-fields.

And if you have so many local variables you lose track of whether an identifier is one, you have most assuredly violated one of the guidelines for managing complexity most grievously.

Try to extract a parameter-object, try to split your function in multiple simpler ones, you most certainly should refactor your code unless you like drowning in minutiae and complexity, as well as have no regard for maintainability.

Now that we have established that the purpose of "this-is-a-member"-decorations no longer holds as the function-scope should be too small and the global scope does not exist, there is one disadvantage to those markers: They inhibit moving arguments / local variables to members, or the other way around.

Deduplicator
  • 9,209
12

Why do developers avoid prepending namespaces with the using namespace directive?

System.DateTime() is much more explicit than DateTime(). It tells me exactly what I'm dealing with. Is it just because we're lazy typists?

No. We are lazy typists, but that's not why.

We prefer coding styles that let us ignore detail and focus on abstractions. Forcing names to communicate structure details is distracting. When I'm working on a complicated algorithm I don't want names that insist on reminding me every little detail about the thing I'm working with. I just need the name to keep me from confusing Timer and DateTime. I'll worry about if those are compatible somewhere else.

It's the same reason you don't want two guys on your team named Jon. The fact that they have last names is not a reason to give them prefixes or suffixes. I'm just going to call you Skeet. Anything more is a flat out pain.

candied_orange
  • 119,268
11

Let's expand a bit.

There are 3 common prefix styles, all of which are occasionally encountered in c# code:

  • m_
  • _
  • this.

Such prefixes are commonly used in the private implementation of a class. The Microsoft recommendation is primarily about the exposed parts of a class.

The advantage of using m_ over _ is that the prefix can be the same in your entire codebase if you use c# as well as languages where using _as a prefix is not allowed.* The advantage of m_ over this. is that it's shorter and that you won't accidentally forget about the prefix.

The advantage of _ over m_ is that it's shorter and that anything starting with the prefix is sorted at the top is sorted alphabetically by a tool. The advantage of _ over this. is that it's shorter and that you won't accidentally forget about the prefix.

The advantage of this. over m_ and _is that you can use it in a codebase where _ or m_ are not an accepted and universal convention. That also means nobody needs to know about the _ or m_ convention, which can be seen as making things simpler. As a downside, because the compiler doesn't care about this prefix, the this. prefix will occasionally be missing, and as such not be as reliable as an indicator.


*Once you start accessing C# classes that use _ from C++/CLI (which really really shouldn't use _), you'll notice that agreeing on a common prefix is more complex than it should be. Deciding to not have a prefix gets rid of that noise. Combine this with Deduplicator's answer, which I'll paraphrase as "the advantage of a prefix is almost negligible", and it gives us: "There's a tiny problem when using prefixes, and a tiny upside, thus it's a valid choice to just not use them".


There's an older question on stackoverflow related to this.

Peter
  • 3,778
6

It should be noted that the MS style guide only talks about public and protected methods and variables. ie The ones other devs will see if they use your library.

The idea being that Microsoft libraries are given a standard look and feel to developers consuming them.

You are free to use whatever style you like on your private or local variables.

Having said that variable prefixes are discouraged in general for a number of reasons

  • They can be wrong, and hence misleading
  • If you are prefixing by variable type its not clear how you handle classes that you have created.
  • There are a number of conventions and they don't always agree. What you find helpful another dev might find unhelpful
  • In the case of member variables you can use this 'this.' keyword to indicate the scope and the complier will enforce it.
Ewan
  • 83,178
5

The "member" prefix is kind of an implementation detail. It distracts your attention from the problem domain to the technical solution domain which biases your mind when thinking of possible refactorings. – me

can you explain further? Yours is the only reason I've seen for why to not use the prefix and I don't understand it ... (by which I mean, the other things people are saying are reasons why I don't have to use it, which is not the same as why I shouldn't) – Betty Crokker

My point is extending the answers of @CandiedOrange and @Ewan.

Prefixes make refactoring harder

As your code evolves variables and methods may change their scope. Eg. you may create a private method and later finding out that it should be available to other (new) classes too. Similar may happen to method parameters and local variables.

Let's say you create a Tax calculator. According to the principle of lease visibility scope for variables you start with a method that takes both, the tax rate and the base value as parameters:
(example may look Java-ish...)

class TaxCalculator{
   double Calculate(double p_TaxRateInpercent, double p_BaseValue){
     return (100+p_TaxRateInpercent)/100 * p_BaseValue;
   }
} 

next you have to implement the reverse operation and according to TDD you do it with the least effort:

class TaxCalculator{
   double Calculate(double p_TaxRateInpercent, double p_BaseValue){
     return (100+p_TaxRateInpercent)/100 * p_BaseValue;
   }
   double CalculateBase(double p_TaxRateInpercent, double p_TaxedValue){
     return p_TaxedValue/((100+p_TaxRateInpercent)/100);
   }
} 

Next TDD wants you to refactor the code to become cleaner which is to reduce the parameter list of both methods.
(Yes, you would extract the doubled calculation first, but let me get my point...)
The obvious solution is to change tax rate into a member variable by passing it as a constructor parameter.

class TaxCalculator{
   double m_TaxRateInpercent;
   TaxCalculator(double p_TaxRateInpercent){
     m_TaxRateInpercent = p_TaxRateInpercent;
   }
   double Calculate(double p_BaseValue){
     return (100+m_TaxRateInpercent)/100 * p_BaseValue;
   }
   double CalculateBase(double p_TaxedValue){
     return p_TaxedValue/((100+m_TaxRateInpercent)/100);
   }
} 

As you can see we had to change all lines of our existing methods (any line we used p_TaxRateInpercent to be exact.

The problem is, that you have no support from your IDE to do the renaming throughout the class. The only help it search/replace which will also change the constructor or any part that accidentally contains the string p_TaxRateInpercent.
You IDE might offer a change to ... refactoring for undefined variable names but this may be restricted to the scope of the method

Without the prefix only the method signatures would have changed. No renaming would have been needed at all.


Prefixes clutter SCM history when changed

Also the SCM records the change of the prefix as changes in the logic although the logic didn't change! The SCMs history is cluttered with this technical change hiding what is important and raising the risk for conflicts with the (real logic) changes of others.

3

For me, if I'm reading through someone else's code, and I see this:

count = 3;

I assume that 'count' is a variable local to that function and I'm doing something that will be used elsewhere in the function

And you will be absolutely right if you are reading source code which respects C#'s style conventions. In such code:

this.count = 3;

assigns a value to a field.

count = 3;

assigns a value to a local variable.

Therefore, C#'s style conventions are clear and unambiguous. They force you not to use any prefix simply because you don't need one.

As for the source code for which the authors decided to use their personal conventions instead, you should ask them personally why they made a choice to do so. If they don't use prefixes such as underscores, while not using this. either, it would effectively lead not only to difficult to read code, but also cases where an additional convention would be needed:

public class Hello
{
    private string greetings;

    public Hello(string greetings)
    {
        greetings = greetings; // Wait, what is that?!
    }
}

Doesn't C# have the this keyword? Couldn't you refer to members using this, such as this.count?

Yes, but (1) it's more typing, and (2) it's easy to forget. If the field is named m_count I don't have to remember to type this.m_count

Here, however, you're wrong.

It's more typing when you write your code in Notepad. With an IDE with auto-completion or, better, IntelliSense, the comparison between this.count and m_count is not as obvious. Note the Shift+- required to type the underscore.

As for “easy to forget,” again, this is relevant only for the users of Notepad. Not only StyleCop and Resharper won't let you forget putting this. when needed, but after a few hours of programming, putting this. when needed becomes a habit.

1

I use _ prefix for all member variables. I hate 'this' prefix because, while some claim it's the right way of doing things - it adds a lot of noise/clutter to your codebase. A single underscore is also a common practice in Microsoft's samples.

So in your example I'd have:

int _count = 10;
Eternal21
  • 1,604