19

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?

  • 9
    Doesn't C# have the this keyword? Couldn't you refer to members using this, such as this.count? – FrustratedWithFormsDesigner Jun 14 '17 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 '17 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 '17 at 21:19
  • 4
    Still relevant post from Joel. – Kasey Speakman Jun 14 '17 at 21:19
  • 3
18

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.

  • 2
    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. – Betty Crokker Jun 14 '17 at 21:16
  • Andy posted literally the same instant I did. I saw the "1 new comment" pop up as I clicked "add answer". As far as those tools, two of them are in the IDE already. Printouts... why are you doing that? – Kevin Fee Jun 14 '17 at 21:17
  • 1
    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 ... – Betty Crokker Jun 14 '17 at 21:40
  • 8
    @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 '17 at 21:44
  • 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 '17 at 22:01
17

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.

  • Once you dot into it, it could also be a class or namespace. – CodesInChaos Jun 15 '17 at 8:03
  • 3
    I don't think this really answers the question. – Vladimir Stokic Jun 15 '17 at 8:54
  • 5
    @FrankHileman Actually, it is. It explains why there is no good reason for uglifying a name. – Deduplicator Jun 16 '17 at 17:09
  • 2
    "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. – Frank Hileman Jun 16 '17 at 21:48
  • 1
    @Deduplicator beauty is in the eye of the beholder. Conventions I once considered ugly, I now appreciate as useful. – Frank Hileman Jun 16 '17 at 21:55
11

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.

  • 2
    This doesn't seem to answer the question. There is no general preference or convention for private fields in .net. – Frank Hileman Jun 14 '17 at 22:47
  • 12
    @FrankHileman In general, we prefer good names. Conventions do not create good names. Conventions create names like McOhPlease Von StopItAlreadyStine. – candied_orange Jun 15 '17 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. – Frank Hileman Jun 16 '17 at 17:04
7

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
    Nice comparison. However, I find that not using any prefix works well in practice. – Phil1970 Jun 18 '17 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.
  • 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. – Frank Hileman Jun 14 '17 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 '17 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. – Betty Crokker Jun 14 '17 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 '17 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 '17 at 22:40
4

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.

  • 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 '17 at 22:34
  • 1
    RubberDuck is right. "this." is a prefix, although, it does have compiler meaning. – Frank Hileman Jun 14 '17 at 22:49
4

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.

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, privacy policy and cookie policy

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