可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened,
visit the help center for guidance.
Closed 8 years ago.
I've never been a fan of Hungarian notation, I've always found it pretty useless unless you're doing some really low level programming, but in every C++ project I've worked on some kind of Hungarian notation policy was enforced, and with it the use of some 'not-really-Hungarian' prefixes as m_ for fields, s_ for statics, g_ for globals and so on.
Soon I realized how much useless it was in C# and gradually started to drop all of my old habits... but the 'm_' thing. I still use the m_ prefix on private fields because I really find it very useful to being able to distinguish between parameters, locals and fields.
The naming conventions for fields page at MSDN says I shouldn't, but it does not say why (the way e.g. Google's conventions generally tend to rationalize their prescriptions).
Are there reasons why I shouldn't or is it only a matter of style. If it is the latter, are prefixes generally considered a bad style and can I expect negative reactions from other people working on the codebase?
回答1:
I like the underbar prefix for member fields. Mostly I like it because that way, all of my member fields are shown alphabetically before my methods in the wizard bar at the top of the screen.
回答2:
When you should:
- When your project coding guidelines say you should
When you shouldn't:
- When your project coding guidelines say you shouldn't
If you don't have any guidelines yet, you're free to choose whatever you or your team want and feel most comfortable with. Personally when coding C++ I tend to use m_
for members, it does help. When coding in other languages, particularly those without true classes (like Javascript, Lua) I don't.
In short I don't believe there is a "right" and a "wrong" way.
回答3:
The auto-implemented property feature in C# 3.0 creates less of a need for this convention one way or the other. Instead of writing
string m_name;
public string Name { get { return m_name; } }
or
string _Name;
public string Name { get { return _Name; } }
(or any other convention), you can now write
public string Name { get; private set; }
Since you no longer need the explicit backing store variable, you no longer have to come up with a name for it; thus avoiding this entire discussion.
Obviously, this argument doesn't apply when you really need explicit backing store such as to perform validation.
回答4:
As some have alluded to, the MS guidelines say:
Do not use a prefix for field names.
For example, do not use g_ or s_ to
distinguish static versus non-static
fields.
I happen to agree with this. prefixes make your code look ugly and waste space with inconsequential characters. Having said that, it is often common to use fields to back properties where both the field and the property would have the same name (with the private field being camel case and the property being pascal case). In VB, this doesn't work, since VB isn't case-sensitive. In this scenario, I recommend the use of a single _ prefix. No more, no less. It just looks cleaner, IMHO.
回答5:
I have experimented with m_, s_, just _, and no prefix at all. I have settled on using just _ for all static and instance variables. I don't find it important to distinguish static variables from instance variables. In theory it sounds good, in practice it doesn't create a problem.
A coworker once made a convincing argument to eliminate all prefixes, we tried it on one project and it worked better then I expected. I carried it forward to my next project and became annoyed that it "interferes" with Intellisense. When you have the following situation
int foo;
public int Foo
{
get { return foo; }
}
Starting to type foo will suggest both the instance variable and the property. Prefixing the variable with an underscore eliminates the annoying double suggestion, so I switched back to using just _.
回答6:
I try to follow the MSDN .NET library guidelines. They include a naming guidelines section.
Obviously, these are secondary to your project guidelines.
回答7:
I prefer to mark property backing fields (although as already mentioned .NET 3.0+ reduces the need thanks to Automatic Properties) with underscores but not the "m". For one it puts them at the top of the InteliSense list when I come to use them.
I will admit that I need to brush-up on the guidelines on MSDN, things can change so quickly these days.
回答8:
With tools like resharper there's really no reason for prefixes. Also if you write short methods, you should be able to tell really quickly where the var is coming from. Finally, I guess I wouldn't really see the need to tell a difference between a static or not because again resharper is going to red line it if you try to do something you're not able to. Even without resharper you're probably saved by the compiler.
回答9:
I always prefix member variables with m_ and static variables with s_ for the same reasons that you state. Some people prefix member variables with an underscore, but I've always found this a bit odd looking (but that's just a personal preference).
Most people I work with use the m_/s_ prefix. I don't really think it matters too much what you use, as long as you're consistent.
回答10:
I never use them. It encourages sloppy coding.
The MSDN coding guidelines, that's where it's at.
回答11:
Here are a few reasons to use _ (and not m_).
(1) Many BCL guys do it despite MS's naming guide. (Check out their blog.) Those guys write the framework, so they have some good habits worth copying. Some of the most helpful example code on MSDN is written by them, and so uses the underscore convention. It's a de-facto industry standard.
(2) A single underscore is a noticeable yet unobtrusive way to disambiguate method and class-level variables by simply reading the source. It helps people understand new (or old) code at-a-glance when reading it. Yes, you can mouse-over to see this in an IDE, but we shouldn't be forced to. You may want to read it in a text editor, or dare I say it, on paper.
(3) Some say you don't need any prefix as methods will be short, and later if needed you can change the field to an auto-implemented property. But in the real world methods are as long as they need to be, and there are important differences between fields and properties (e.g. serialization and initialization).
Footnote: The "m" for member in m_ is redundant in our usage here, but it was lower case because one of the ideas in many of these old naming conventions was that type names started with upper case and instance names started with lower case. That doesn't apply in .NET so it's doubly redundant. Also Hungarian notation was sometimes useful with old C compilers (e.g. integer or pointer casting and arithmetic) but even in C++ its usefulness was diminished when dealing with classes.
回答12:
There is one important difference between C++ and C#: Tool support. When you follow the established guidelines (or common variations), you will get a deep level of tool support that C++ never had. Following the standards allows tools to do deeper refactoring/rename operations than you'd otherwise be capable of. Resharper does this. So stick with one of the established standards.
回答13:
As @John Kraft mentions, there is no "correct" answer. MattJ is the closest -- you should always follow your company's style guidelines. When in Rome, and all that.
As for my personal opinion, since it's called for here, I vote that you drop m_
entirely.
I believe the best style is one where all members are PascalCased
, regardless of visibility (that means even private
members), and all arguments are camelCased
. I do not break this style.
I can understand the desire to prefix property backing store field; after all you must differentiate between the field and the property, right? I agree, you must. But use a post-fix.
Instead of m_MyProperty
(or even _MyProperty
, which I've seen and even promoted once upon a time), use MyPropertyValue
. It's easier to read and understand and -- more importantly -- it's close to your original property name in intellisense.
Ultimately, that's the reason I prefer a postfix. If I want to access MyPropertyValue
using intellisense you (typically) type "My <down-arrow> <tab>
", since by then you're close enough that only MyProperty
and MyPropertyValue
are on the list. If you want to access m_MyProperty
using intellisense, you'll have to type "m_My <tab>
".
It's about keystroke economy, in my opinion.
回答14:
I never do this and the reason why is that I [try to] keep my methods short. If I can see the whole method on the screen, I can see the params, I can see the locals and so I can tell what is owned by the class and what is a param or a local.
I do typically name my params and locals using a particular notation, but not always. I'm nothing if not inconsistent. I rely on the fact that my methods are short and try to keep them from doing X, Y and Z when they should be only doing X.
Anyhow, that's my two cents.
回答15:
Unless I'm stuck with vi or Emacs for editing code, my IDE takes care of differential display of members for me so I rarely uses any special conventions. That also goes for prefixing interfaces with I or classes with C.
Someone, please, explain the .NET style of I-prefix on interfaces. :)
回答16:
what i am used to is that private properties got small underscone f.ex "string _name". the public one got "Name". and the input variables in methods got small letter"void MyMethod(string name)".
if you got static const is often written with big letters. static const MYCONST = "hmpf"
.
回答17:
I never use any hungarian warts whenever I'm given the choice. It's extra typing and doesn't convey any meaningful information. Any good IDE (and I define "good" based on the presence of this feature, among others) will allow you to have different syntax highlighting for static members, instance members, member functions, types, etc. There is no reason to clutter your code with information that can be provided by the IDE. This is a corollary to not cluttering your code with commented-out old code because your versioning system should be responsible for that stuff.
回答18:
The best way is to agree on a standard with your colleagues, and stick to it. It doesn't absolutely have to be the method that would work best for everyone, just agreeing on one method is more important than which method you actually agree on.
What we chose for our code standard is to use _ as prefix for member variables. One of the reasons was that it makes it easy to find the local variables in the intellisense.
Before we agreed on that standard I used another one. I didn't use any prefix at all, and wrote this.memberVariable
in the code to show that I was using a member variable.
With the property shorthand in C# 3, I find that I use a lot less explicit member variables.
回答19:
The closest thing to official guidelines is StyleCop, a tool from Microsoft which can automatically analyse your source files and detect violations from the recommended coding style, and can be run from within Visual Studio and/or automated builds such as MSBuild.
We use it on our projects and it does help to make code style and layout more consistent between developers, although be warned it does take quite a bit of getting used to!
To answer your question - it doesn't allow any Hungarian notation, nor any prefixes like m_
(in fact, it doesn't allow the use of underscores at all).
回答20:
I don't use that style any longer. It was developed to help you see quickly how variables were being used. The newer dev environments let you see that information by hovering your mouse over the variable. The need for it has gone away if you use those newer tools.
回答21:
There might also be some insight to be gleaned from C++ Coding Standards (Sutter, Herb and Alexandrescum Andrei, 2004). Item #0 is entitled "Don't sweat the small stuff. (Or: Know what not to standardize.)".
They touch on this specific question a little bit by saying "If you can't decide on your own naming convention, try ... private member variables likeThis_ ..." (Remember use of leading underscore is subject to very specific rules in C++).
However, before getting there, they emphasize a certain level of consistency "...the important thing is not to set a rule but just to be consistent with the style already in use within the file..."
回答22:
The benefit of that notation in C/C++ was to make it easier to see what a symbol's type was without having to go search for the declaration. These styles appeared before the arrival of Intellisense and "Go to Definition" - we often had to go on a goose chase looking for the declaration in who knows how many header files. On a large project this could be a significant annoyance which was bad enough when looking at C source code, but even worse when doing forensics using mixed assembly+source code and a raw call stack.
When faced with these realities, using m_ and all the other hungarian rules starts to make some sense even with the maintenance overhead because of how much time it would save just in looking up a symbol's type when looking at unfamiliar code. Now of course we have Intellisense and "Go to Definition", so the main time saving motivation of that naming convention is no longer there. I don't think there's much point in doing that any more, and I generally try to go with the .NET library guidelines just to be consistent and possibly gain a little bit more tool support.
回答23:
I am sure that I will get flamed for this but so be it.
It's called Microsoft's .NET library guidelines but it's really Brad Abrams's views (document here) - there are other views with valid reasons.
People tend to go with the majority view rather than having good solid reasons for a specific style.
The important point is to evaluate why a specific style is used and why it's preferred over another style - in other words, have a reason for choosing a style not just because everyone says it's the thing to do - think for yourself.
The basic reason for not using old style Hungarian was the use of abbreviations which was different for every team and difficult to learn - this is easily solved by not abbreviating.
As the available development tools change the style should change to what makes the most sense - but have a solid reason for each style item.
Below are my style guidelines with my reasons - I am always looking for ways to improve my style to create more reliable and easier to maintain code.
Variable Naming Convention
We all have our view on variable naming conventions. There are many different styles that will help produce easily maintainable quality code - any style which supports the basic essential information about a variable are okay. The criteria for a specific naming convention should be that it aids in producing code that is reliable and easily maintainable. Criteria that should not be used are:
It's ugly
Microsoft (i.e. Brad Abrams) says don't use that style - Microsoft does not always produce the most reliable code just look at the bugs in Expression Blend.
It is very important when reading code that a variable name should instantly convey three essential facts about the variable:
it’s scope
it’s type
a clearly understand about what it is used for
Scope: Microsoft recommends relying totally on IntelliSense . IntelliSense is awesome; however, one simply does not mouse over every variable to see it's scope and type. Assuming a variable is in a scope that it is not can cause significant errors. For example, if a reference variable is passed in as a parameter and it is altered in local scope that change will remain after the method returns which may not be desired. If a field or a static variable is modified in local scope but one thinks that it is a local variable unexpected behavior could result. Therefore it is extremely important to be able to just look at a variable (not mouse over) and instantly know it's scope.
The following style for indicating scope is suggested; however, any style is perfectly okay as long as it clearly and consistently indicates the variable's scope:
m_ field variable
p_ parameter passed to a method
s_ static variable
local variable
Type: Serious errors can occur if one believes they are working with a specific type when they are actually working with a different type - again, we simply do not mouse over ever variable to determine its type, we just assume that we know what its type is and that is how errors are created.
Abbreviations: Abbreviations are evil because they can mean different things to different developers. One developer may think a leading lower case "s" means string while another may think it means signed integer. Abbreviations are a sign of lazy coding - take a little extra time and type the full name to make it clear to the developer that has to maintain the code. For example, the difference between "str" and "string" is only three characters - it does not take much more effort to make code easy to maintain.
Common and clear abbreviations for built-in data types only are acceptable but must be standardized within the team.
Self Documenting Code: Adding a clear description to a variable name makes it very easy for another developer to read and understand the code - make the name so understandable that the team manager can read and understand the code without being a developer.
Order of Variable Name Parts: The recommended order is scope-type-description because:
IntelliSense will group all similar scopes and within each scope IntelliSense will group all similar types which makes lookups easy - try finding a variable the other way
It makes it very easy to see and understand the scope and to see and understand the type
It's a fairly common style and easy to understand
It will pass FxCop
Examples: Here are a few examples:
m_stringCustomerName
p_stringCustomerDatabaseConnectionString
intNumberOfCustomerRecords or iNumberOfCustomerRecords or integerNumberOfCustomerRecords
These simple rules will significantly improve code reliability and maintainability.
Control Structure Single Line Statements
All control structures (if, while, for, etc.) single line statements should always be wrapped with braces because it is very easy to add a new statement not realizing that a given statement belongs to a control structure which will break the code logic without generating any compile time errors.
Method Exception Wrapping
All methods should be wrapped with an outer try-catch which trap, provide a place to recover, identify, locate, log, and make a decision to throw or not. It is the unexpected exception that cause our applications to crash - by wrapping every method trapping all unhandled exceptions we guarantee identifying and logging all exceptions and we prevent our application from ever crashing. It takes a little more work but the results is well worth the effort.
Indentation
Indentation is not a major issue; however, four spaces and not using tabs is suggested. If code is printed, the first printer tab usually defaults to 8 spaces. Different developer tend to use different tab sizes. Microsoft's code is usually indented 4 space so if one uses any Microsoft code and uses other than 4 spaces, then the code will need to be reformatted. Four spaces makes it easy and consistent.
回答24:
If you are not coding under a particular guideline, you should keep using your actual m_ notation and change it if the project coding guidelines says so.
回答25:
Be functional.
- Do not use global variables.
- Do not use static variables.
- Do not use member variables.
If you really have to, but only if you really have to, use one and only one variable to access your application / environment.