Nomenclature standard in code for C#

Asked

Viewed 8,111 times

48

I recognize that it is common for each language to use a pattern to compose its identifiers (variables, constants, objects, controls etc).

In the case of C#, what would be the best practices regarding upper/lower case, size and use of special characters?

3 answers

49

  • Adopt the same uppercase pattern of . NET according to the table below. When using acronyms, prefer to keep only the first letter capitalized for easy reading. The member being static, constant or read-only does not affect the pattern. There is controversy whether protected fields should actually be camelCase or is better with PascalCase. It depends on whether you are considering it closer to being private or closer to being public.
Pascalcase camelCase
Classes Local variables
Assembly Method parameters
Classes Private and protected camps
Structs
Intefaces (always with the I before the names)
Delegates
Enums
Methods
Estates
Public camps
Events

General recommendations for writing

  • Try to use a more fluent way to give understanding to what you want but don’t overdo it. Try to use a language that is suitable for the domain being developed for that specific task.
  • Rarely should a number be part of a name of any identifier. If you use it it must have some meaning. Ex.: Norma452.
  • Avoid names that can be confused with something else. Ex.: b001.
  • Try to keep similar names for similar things.
  • Names should be easy to locate with code search tools. You should easily find what you want, preferably nothing more and nothing less than what you want. Keep this in mind.
  • Decide whether to use accentuation on identifiers or not and maintain the standard, if accept accents, everyone has to respect the correct accentuation, can not keep choosing moments not to accentuate.
  • DoThis() may be great as a generalized example but has no meaning to the code. The most important thing is give significant names. Especially don’t give names that mean anything else, even if eventually. Ex.: string nonBlank = " ";
  • Try to understand the subtleties of names. Counter is an accountant, Count is a count and TotalCount is the count totalizer. Be as specific as possible. SalveNome() is better than SalveCampo() unless the second saves any field to be specified.
  • Avoid abbreviations unless it makes sense for everyone and does not create ambiguities. The abbreviation can be so well known that it can be even better. Ex.: Ftp, UI, IO, DB, PK, AlgumaCoisaInfo, Config, ValorIcms, Id, Args, ex (for what can only be an exception), i for loops (i has an obvious meaning for any programmer), temp or even tmp (but do not use both). In local variables the abbreviation is not so problematic if it does not create incomprehensible mnemonics. It’s best to avoid them, but you don’t have to exaggerate. It becomes a problem if everything is abbreviated or not able to understand the intention of the variable by any programmer with minimal experience. Don’t ask me why it’s better Pascalcase in Ftp but ALLCAPS in UI, IO, etc. I imagine it is the fact that there are only two letters in the acronym. Already Id is one word. Some prefer ID. I don’t, but I maintain a pattern.
  • Do not use underscore (underlined) in identifier names unless it has a very strong reason, perhaps to avoid possible conflicts in code dealing with lower level situations (generators). Especially don’t use the prefix m_. Underlining can be used for an irrelevant parameter in a lambda. Ex.: (_, __) => FazAlgo(); when you know you need to receive two arguments but they will not be used in your execution.
  • It has become clear that hungarian notation should not be used. An identifier should indicate its meaning in that context and not some technical feature of it. Yet you say you’re wearing a TextBox with descrição is not Hungarian notation, it is important to understand what that identifier is. Already a method GetInt() may be since it is not saying what is taking and yes the kind of what is taking, the intention is this, it is not a simple feature. carArray probably Hungarian, prefer to carros.
  • Avoid reserved words usually present in other languages running on top of the CLR.
  • If the type makes sense in an identifier name (typically a method), prefer the name of the type known by the CLR and not the name defined in C#, so the identifier can be easily used in other languages. I could even avoid this in private identifiers or what is absolutely certain that will never be used in another language, but for coherence, it is better not to create exceptions. This goes for naming identifiers, not for using type declaration.
  • Look for some easy common terms and program their use when really cannot identify the meaning of the identifier or it is not relevant. Use value or valor, item, etc..
  • Try to find the correct semantics of what you are trying to do and mainly maintain a correct relationship between terms that complement each other. For example: Begin comes before a End, not to be confused as a Start that comes before a Stop and a Initiate before Finish, one Open before Close, Lock before Unlock, Block and Deblock, Head and Tail, Header and Footer, Before and After, Read and Write, Input and Output, First and Last, Previous and Next, Increment and Decrement, Enter and Leave, Add and Remove, Create and Destroy, Insert and Delete, Show and Hide, Suspend and Resume, Top and Bottom, etc. Others are more complicated to state or depend on context. Do house with Cancel? And Go has to do with Quit? Or the reverse between the above terms? And what about the use Run, Execute, Perform, Abort?. It is good to learn before using. Understand the difference between Find, Seek, Search, Lookup, Scan, Traverse, Locate, Select, Query, Pick, Trace, GetAbcXxx and similar and its translations. Do not stick to these words, they are just examples of similar concepts that can be defined more precisely with the correct word. Calcule is different from Pegue which is different from Leia. A property TemPedidos is very different from a method VerifiqueExistênciaDePedidos(). Understand the difference between Increment, Add, Plus and Accumulate. Choose names that identify if there will be side effect, mutation of the object or not.
  • Avoid names that cause double negative when using a not. Ex.: !family.hasNoChildren. Be affirmative.
  • If it is difficult to give a name to a type or method it probably does more than it should or is not clear what it does or why it exists. If you need to use a And or E There’s a chance something’s wrong.
  • There is usually no problem using a variable or property with the same type name as camelCase (Color color = Color.Red;). This should only be avoided if the variable name does not quite indicate what it is doing there. Contextual meaning can be lost when adopting this pattern (maybe better Color statusColor = Color.Red;).
  • Boolean type identifiers may, or even should, have prefixes indicating a capability. Ex.: is, can, has, isThere (some prefer to use only the has), allow (which may be the same as can). Or in English é or eh, está or estah (usually followed by a verb in the participle or adjective), pode (usually followed by a verb in the infinitive), tem (probably followed by a noun), Existe (followed by a noun). The plural can be used, or another conjugation, e.g. .: foiTentado. And remember that an enumeration usually gives more semantics than a boolean, even when there are only two states. The Boolean semantics is just to say whether it is true or false, do not use for other things that have only two states.

Variables

  • Variables that hold collections may be plural. This is valid in most cases but there are situations that may not be ideal. There are those who use collective in these cases.
  • In events it is common to use the suffix EventArgs for the parameter that will receive the event arguments. This makes clear the intent of this parameter. Probably this parameter will be a subclass type of the EventArgs.
  • Variables may have several forms according to the context but the most common is that they are nouns.

Types

  • Classes, structures and enumerations must be nouns even if they are adjectives or compounds. Interfaces can be nouns or adjectives indicating a capability, being common ending in able or ável. In some projects abstract classes usually carry the suffix Base. I have my doubts whether this is consistent, as far as I know is not recommended by Microsoft. Using the base class name as part of the name of the new derived class is usually a good option, but care must be taken to avoid exaggerations and long names that end up not identifying well what the class is.
  • Static classes with extension methods must have the suffix Extension. Some people think Ext is sufficient. In some cases a normal static class may have the suffix Utility or Helper but these classes should be avoided. If it has any well-defined function the suffix is unnecessary. This is reflected in Math and Console.
  • Enumerations should use the singular unless in the rare cases it makes much more sense to be in the plural which is the case of the use as [Flags]. And don’t use a prefix or suffix Enum in the name. Redundancies of this kind in other things, especially in column names in databases is one of the biggest abuses I see in nomenclature.
  • Exceptions must have the suffix Exception to avoid confusion. This way makes clear to what should be used.
  • Attributes must end with Attribute in its definition. The compiler himself knows that the use of attributes does not use the suffix, that is, he knows unequivocally that it is an attribute and that the original name needs a suffix. Not putting the suffix in the statement can cause problems, as well as putting in use.
  • Some say that guys delegates must have the suffix Delegate. Some people find it unnecessary. Microsoft habitually use suffix but seems to be "as necessary" as the suffix Enum in an enumeration. Prefer to use a lambda and don’t worry about it :).
  • Prefer to use capital single letters to identify the slots of generic types (T, U, K, V). If you have a good reason you can use more meaningful words but don’t use names that can be confused with existing types (you never know when it will cause confusion), especially don’t use Type to avoid confusion with the type Type. If using a more descriptive name use the prefix T. Ex.: TKey and TValue.

Type members

  • Methods are usually verbs, mainly in the imperative, often followed by the noun to which they refer. A method is an action you are ordering the computer to do. Delegates do not usually differ from common methods. But these rules may vary to give a more fluent reading for what is desired. Just don’t try to make the whole code look like fluent English, or worse, Portuguese, because that’s not possible without making the code even more confusing. The method may indicate on their behalf what they are returning (but in general, not their type), especially those that begin with Get or Pegue or Compute, etc. There are those who use PegarXXX() or CalcularXXX that apparently would be the infinitive. I do not know if this is an error by ignorance or there is some reason for conscious choice. I believe more in the first.
  • The suffix Async should always be used in methods that have this feature. It is important to identify a method with such a special feature and helps to distinguish it from the synchronous version.
  • Events are verbs in the gerundium (pre-event) or past participle (post-event) as per the situation. Avoid creating events with suffix Before or After or similar names. If the event should perform the action the name must be in the infinitive. Ex.: Deleting, Deleted and Delete. Event handlers must have the prefix on. There are controversies whether there should be the aportuguese form for on.
  • Estates and public fields tend to be used as adjectives. If you use as a verb, there may be something wrong.
  • Enumeration members can take various forms, nouns, adjectives, verbs in some conjugation.
  • Avoid placing so-called "sentinel limbs" that are artificial members of enumerations that help manipulate them. Put only natural members into the domain. Ex.: NotSelected.
  • Avoid any redundancy unless it serves to avoid ambiguity. Prefer Line.GetLength() à Line.GetLineLength().

Archive, Assembly and Namespace

  • Use one class per file and name the filing cabinet with the same class name.
  • Prefer to use fully qualified names (including namespace) in small examples or short files where only one member of a namespace is used. And prefer to use the directive using when using several members of a namespace in larger files (most cases).
  • Don’t name namespaces with an internet domain (perhaps the worst case of super-engineering I have ever seen). You can use the company name and then the product or technology name in a subgroup but don’t try to make the name unique by abusing the subgroups. If indeed the name of the company responsible for the namespace is very common, use a variation that leaves it unique. The point should be used to separate clusters that make sense and not to separate words. Prefer ServiceModel à Service.Model.
  • Namespaces should not have the same name as its member types. If this is necessary, try to make some change how to put the namespace plural. Remember that it is possible to have some redundancy in namespaces since they do not necessarily appear in the use of their members. So have a class XmlDocument within the NS Xml is not a redundant exaggeration.
  • Avoid creating polluting members namespaces that you have not created (from a third party). The best reason not to follow this recommendation is to create extension methods, but not to abuse it.
  • Whenever possible the name of a Assembly must follow the name of namespace. Organize a namespace (at least the main part of it) by Assembly is a good organization but does not need to be blindly followed.

Patchwork

  • In a more modern API use the same old name with a suffix indicating that it is the new version, if possible indicating the novelty. This makes it easier to find both. Or prefer a name that is more meaningful when the previous name was not well chosen. Ex.: AlgumaCoisaAsync, FazAlgoEx.
  • When it really is not possible to give a good name to an identifier use a comment close to the statement to help give better understanding. But this must be rare.
  • Not related to the name but to the readability: declare the variables as close as possible to where it will be used, there is no more need or advantage in declaring everything at the beginning of the code. Members yes, can be declared organized by their function on type.
  • If the development is international everything must be in English. If it is certain that you will never leave the domain of your country, you can use your language where the domain is in your language. Leave in English the most technical things, the most related domain to the mechanism.
  • When guidelines conflict you have to choose one, obvious. I prefer to choose the one that seems to cause less problems or at least that pleases me more. This usually matches what language/framework prefers. Ex.: CA1500 comes from the compiler. SA1309 comes from an external tool. I prefer the first one. Because it seems to me cleaner and does not cause any problem.
  • Avoid bringing to C# excellent (or not so much) conventions from other languages. I already identify that a programmer is lazy or does not know how to program in C# when he puts constants as ALL CAPS. This era useful in C because it was the only way to indicate, at least for the programmer, that an identifier was a constant. After that it was no longer important but people continued to do so (read on the monkey experiment, here at Sopt it happens a lot this, just can’t think that doing what has always been done is wrong by definition, the problem is not knowing why). They took this to other new languages by the influence of their authors or of their own volition. This example is a variation of Hungarian notation. You use a convention to demonstrate something that doesn’t need to be demonstrated and worse, that can be changed in the future, even if it shouldn’t.

Most of these recommendations were defined by language creators/framework to facilitate and standardize the understanding of the code by all. The most important thing is to maintain consistency between a team. But if you think your code might end up being shared with people you don’t know (here for example) it’s best to try to follow universal standards.

Of course, some conventions help more than others and what helps most is to maintain clarity than what you are trying to indicate there. This is usually only easy to do when you fully master the problem. Naming something eventually is hard enough, imagine naming thousands of things you don’t master in a few days of work.

These conventions facilitate the reading and maintenance of the project. Indirectly thinking about this helps to understand what you are doing. But try to understand the motivations for the recommendation, this can help you more, can help your code be better written beyond the nomenclature.

Obviously I haven’t made a full list of conventions and much less explained each one.

AP’s answer already gave good indications of what should be done to try to achieve a better result, I tried to stick to some guidelines that I found and that I follow or that you could follow.

I disagree a little bit with taking care of names that can impact data traffic. This should not be a concern. If it is important (usually it is not) it is best to create a post-code way to reduce the size. The question of underline It’s not the official recommendation, but of course there’s no such thing as right and wrong at conventions, I’m just pointing that out. Ubiquitous language can be good if you don’t misunderstand what this is, don’t overdo it. It is usually difficult to find universal consensus of what is more ubiquitous. I honestly do not know if it is better nomeTextBox or textBoxNome (this is a TextBox of Nome or is a Nome encapsulated in a TextBox?), then pick one and keep the consistency.

As already said you can use tools to help force these patterns, but only a small part is possible. You can take a look at the rules existing in Stylecop and can create their own.

Always remember that if there is a good reason, do not follow the recommendation. Know that some slips will be punished more intensely than others. And the main thing is, no convention is mandatory. Don’t you like it? Do you think it’s problematic? Is there a good reason not to follow at a certain point? Use another way. Conventions and guides are like good practices, only good when you know when not to follow.

Stylecop evolves.

Style guide of own . NET.

In the There’s only so many answers on the subject on an individual basis.

I write more on the subject in that reply.

I may have missed something, comment.

  • "Try to use a more fluent way to give understanding to what you want but don’t overdo it. Try to use a language that is appropriate to the domain being developed for that specific task." - I think this is paramount, I believe it is the most that can facilitate the understanding of the code.

  • Can you tell me if it’s better to use _ (underline) at the beginning of a private field? I get very confused, I see codes with it, others do not. VS also confuses me, when it creates the private fields and assigns the value from the constructor parameters, it does not use the _, but when is it to convert to a complete property, I think that’s how it’s there, it uses =/

  • 1

    @Viníciusfile you can use, but it is not the standard adopts, there is no advantage in it if you adopt the other standards. Who does it does not follow the standard, including Visual Studio. It has bad things in it and in the documentation.

  • 1

    Excellent answer!! It should be as accepted.

24


Generally speaking, for C#, the default Camel case is widely used. Summarizing, in this pattern, names are composed by simply uniting them without any sort of separator, such as underscore (_). What helps differentiate the words is the FatoDeCadaUmaIniciarComMaiúscula. In addition, choosing the name of the element can contribute - and greatly - to the understanding of your code by the team (and by yourself, when returning after a few months for an eventual maintenance). Below some considerations that may facilitate when choosing the name of your identifiers:

Be clear!

First, choose a name that gives meaning to that element. Read the code again, as if it were a text in Portuguese and try to evaluate if the sentence you just read makes sense, that is, if it is coherent and does not induce the reader to any kind of ambiguity. If you don’t remember what a variable is for (x is a bad name), is likely to have chosen the wrong name.

Abbreviations

Generally, acronyms and abbreviations tend to hinder the understanding of the code, unless they are widely used by everyone in the team and in the company. An increasingly disused pattern, the hungarian notation, provides for the use of abbreviations for naming controls and to this day many people use it to give names to database elements. So a text box could be called txtNome. By opting for more eloquent language, the abbreviation would be replaced by textBoxNome.

Ubiquitous language

Under the influence of Eric Evans, in his book Domain Driven Design, there is a tendency to assign names that express before business and then technology. For a developer this represents a challenge, because we express most of the time using an essentially technical language and full of own terms. Focusing on the business, the txtNome control would be called nomeTextBox, for example. Ubiquitous language is considered the one that all involved speak, which is present in the everyday vocabulary of the organization and facilitates the understanding of a concept by all.

Upper and lower case

In the pattern Camelcase there is a common distinction for the first initial:

  • for Classes, it is in capital letters: SituacaoVenda. For Constants and Enumerators also.
  • for objects, controls and variables, in lower case: notaFiscal, contadorItemNotaFiscal.

Size

The limit for the size of an identifier’s name is common sense only, there is no limitation imposed by the framework. Thus, very long names can take up too much screen space and disturb reading. It is also worth remembering that, for names of controls on the web (in the view itself), the issue of size can impact data traffic, since each character represents a byte.

Special characters

In C#, it is common to use underscore (underline, underscore) to initialize private fields, also known as attributes. They are those elements declared in the class scope and therefore available for all methods of this class. Thus, a field to represent the client repository could be called _clienteRepositorio.

Every language has its reserved words (key words). In C# it is possible to use arroba (@) if it is very necessary for a variable to be called class, for example (@class).

Productivity tools

Visual Studio itself suggests names for controls using these patterns. If you create a menu item with the Clients description, the IDE will suggest that the respective control name be clientsMenuItem, for example.

Another tool that implements these practices is Resharper from Jetbrains. This tool already suggests a much more comprehensive set of good practices, highlighting in the code the nomenclature that escapes the standard.

  • Very complete answer. Congratulations.

  • @Guilhermejsantos and my answer is complete? :)

4

There is a pattern of naming variables and facilitates coding

Methods => Uppercase letter in the first letter example: private void Getcadastrarusuario()

Propreties => Letter Uppercase in the first letter example: public String Name { set; get; }

Event => Uppercase letter in first letter example: public Eventhandler Onchange;

Global Variables in Class Scope => Use '_' before the example variable name: int _variableEmplo = 0;

Internal Variables: => example: int value = 0;

Obs: When referring to a layout item through C# it is important to put the example : this.Buttonsave , because it makes it easy to identify where this variable comes from.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.