28

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?

24
  • 9
    Doesn't C# have the this keyword? Couldn't you refer to members using this, such as this.count? Jun 14, 2017 at 21:05
  • 3
    The m_ prefix is a C++-ism where it avoids name clashes between fields and methods. In C# this isn't an issue because method names ought to start with upper case, fields with lower case.
    – amon
    Jun 14, 2017 at 21:18
  • 4
    If you're printing code in 2017, you're doing something wrong. In the other two scenarios, it should be fairly obvious that count didn't just appear out of no where since it wasn't declare in the method. Frankly the "out of IDE" argument is REALLY weak. Especially since there are even code review tools which work IN the IDE.
    – Andy
    Jun 14, 2017 at 21:19
  • 4
    Still relevant post from Joel. Jun 14, 2017 at 21:19
  • 3

8 Answers 8

24

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.

18
  • 3
    Same answer as to Andy ... yes but ... there are many situations where I am looking at code outside of the IDE. Examples - (1) merge tools. (2) code review tools. (3) (gasp) printouts. Jun 14, 2017 at 21:16
  • 2
    My initial question remains unanswered ... yes, Microsoft said don't use m_ and tool manufacturers followed that, but that's not a technical reason to use m_, it's what is often called "appeal to authority". The only technical reason I've seen to not use m_ came from Timothy Truckle and I don't understand it ... Jun 14, 2017 at 21:40
  • 9
    @BettyCrokker Because m_ adds absolutely no value. The IDE tells you member or not, so the m_ is redundent. Any why are you fixated on m_? Why not l_ (for local)? Why not afsdfjdskfjas_ ? I'm going to downvote the question, because its a silly religious argument anyway. Do whatever you want. The guidelines you're knocking also say "The field-naming guidelines apply to static public and protected fields. Internal and private fields are _not_ covered by guidelines, and public or protected instance fields are not allowed by the member design guidelines. "
    – Andy
    Jun 14, 2017 at 21:44
  • 2
    It adds value to me; it may not add value to you, and that's fine, so you don't have to use it. Bottom line: m_ adds value to me, and I have not seen any technical reason why it hurts anything. Thanks for pointing out the "not covered by guidelines", that helps. Jun 14, 2017 at 21:50
  • 1
    @BettyCrokker OK, but you're asking about guidelines that are made with that assumption. You're also complaining about static tools that are likely using that assumption as well, because "no one" (within an acceptable statistical margin of error) prints out their C# code. I don't know what statistical analysis tools you use, but Resharper is pretty specific: Private fields are "_lowerCase". Public members of any type or "UpperCase", and locals are "lowerCase". Saving on the "m" actually looks pretty nice, anyway.
    – Kevin Fee
    Jun 14, 2017 at 22:01
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.

12
  • Once you dot into it, it could also be a class or namespace. Jun 15, 2017 at 8:03
  • 3
    I don't think this really answers the question. Jun 15, 2017 at 8:54
  • 5
    @FrankHileman Actually, it is. It explains why there is no good reason for uglifying a name. Jun 16, 2017 at 17:09
  • 3
    "uglifying"? If this is the case, it is an opinion-only question. Everyone can have a different opinion about ugliness. There are reasons for preferring one convention over another, but there is no standard convention in this case. Jun 16, 2017 at 21:48
  • 2
    @Deduplicator beauty is in the eye of the beholder. Conventions I once considered ugly, I now appreciate as useful. Jun 16, 2017 at 21:55
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.

3
  • 2
    This doesn't seem to answer the question. There is no general preference or convention for private fields in .net. Jun 14, 2017 at 22:47
  • 12
    @FrankHileman In general, we prefer good names. Conventions do not create good names. Conventions create names like McOhPlease Von StopItAlreadyStine. Jun 15, 2017 at 0:10
  • Conventions are just to make it easier to work with different developer's code. Your answer does address hungarian, but there is no convention for private fields, so the question is based on a false assumption. Jun 16, 2017 at 17:04
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.

1
  • 1
    Nice comparison. However, I find that not using any prefix works well in practice.
    – Phil1970
    Jun 18, 2017 at 0:13
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.
7
  • 2
    Originally I used no prefix at all for fields. Later, I switched to using a single "_" character, as I saw others using it because it moves all fields to the top of the alphabetized member list when you use IDE drop-down list boxes. The lack of a standard convention can be annoying when reading code written by many different developers. Jun 14, 2017 at 22:03
  • after a while you see so many different styles you just ignore them. If you tried to enforce a style you would be constantly refactoring everything
    – Ewan
    Jun 14, 2017 at 22:08
  • 4
    If you apply "They can be wrong, and hence misleading" to most anything, you quickly discover that you shouldn't name variables or functions - they might be wrong after all! And I'm guessing that your second bullet point is supposed to say "classes that you have NOT created"? Or else I just don't understand it ... In any case, it's starting to sound like having a single underscore prefix for non-public fields is an unofficial standard, that's probably the direction we will go. Jun 14, 2017 at 22:36
  • some things are checked by the compiler, so m_count might not be a member variable, but this.count will always be
    – Ewan
    Jun 14, 2017 at 22:39
  • lots of ppl use _ but things change over time, youll find that code written to 'best practice' last year doesnt match this years conventions
    – Ewan
    Jun 14, 2017 at 22:40
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.

0
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.

2
  • 6
    I find that using this only when you need it results in a really inconsistent feel and distracts me far too often. If you're going to use this instead of a prefix, I believe you should always use it. In which case, it becomes a prefix and you might as well use _.
    – RubberDuck
    Jun 14, 2017 at 22:34
  • 1
    RubberDuck is right. "this." is a prefix, although, it does have compiler meaning. Jun 14, 2017 at 22:49
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;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.