56

Why do I get the compiler warning

Identifier 'Logic.DomainObjectBase._isNew' is not CLS-compliant

for the following code?

public abstract class DomainObjectBase
{
    protected bool _isNew;
}
MatthewMartin
  • 32,326
  • 33
  • 105
  • 164
  • 25
    You probably should not be marking non-private members with an underscore anyway. I know that everyone has their own style, but others will almost certainly think that the field is private out of convention. – Ed S. Jul 28 '09 at 17:25
  • @EdS. Which convention? – Pharap Jun 16 '15 at 02:16
  • Seems to have been a VB convention at one time, it also appears to be out of style for C++, C#, more details than will fit in this box found here: https://stackoverflow.com/questions/3136594/naming-convention-underscore-in-c-c-variables – MatthewMartin Jun 16 '15 at 03:10
  • 1
    @Pharap: It's common to name a private member with a leading underscore. I believe that `fieldName` is more common in C# (at least, it's what I see more often than not), but some don't like it, myself included, because it forces you to write `this.` all over the place. – Ed S. Jun 16 '15 at 17:10
  • @EdS. CamelCase for private/protected members is what [MSDN's general naming conventions](https://msdn.microsoft.com/en-us/library/ms229045%28v=vs.110%29.aspx) suggests for C#: . Presumably this issue is one of the reasons why. I have not come across many people who use a leading underscore to indicate a private member, but presumably that's because I use mainly C# and C++ (where it is sometimes avoided because of [the standard library's rules regarding the use of underscores](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier)). – Pharap Jun 17 '15 at 01:26
  • 1
    @Pharap: Actually, they don't: https://msdn.microsoft.com/en-us/library/ms229012(v=vs.110).aspx. *"Internal and private fields are not covered by guidelines"*. You're referring to *static* members, a different beast entirely. Also, there's nothing wrong with using a *single* leading underscore for private identifiers which are followed by a lowercase letter in C++. Anything in the global namespace or followed by a capital, yeah. – Ed S. Jun 17 '15 at 17:30
  • @EdS. I was not referring to static members, if you read the link you sent me it suggests using PascalCasing, I said camelCasing. I was referring to the word choice conventions which warn against using non-alphanumeric characters. The guidelines do not explicitly give a rule for private members, but the naming of private fields should be influenced by the general naming conventions. As for C++ it's true that it doesn't prohibit underscore-camelCasing, but many people prefer to avoid leading underscores altogether as a precaution. – Pharap Jun 18 '15 at 04:03

8 Answers8

80

From the Common Language Specification:

CLS-compliant language compilers must follow the rules of Annex 7 of Technical Report 15 of the Unicode Standard 3.0, which governs the set of characters that can start and be included in identifiers. This standard is available from the Web site of the Unicode Consortium.

If you look this up:

That is, the first character of an identifier can be an uppercase letter, lowercase letter, titlecase letter, modifier letter, other letter, or letter number. The subsequent characters of an identifier can be any of those, plus non-spacing marks, spacing combining marks, decimal numbers, connector punctuations, and formatting codes (such as right-left-mark). Normally the formatting codes should be filtered out before storing or comparing identifiers.

Basically, you can't start an identifier with an underscore - this violates CLS compliant on a visible (public/protected) field.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 1
    What is a "letter number"? – Kevin Mar 01 '17 at 16:52
  • 2
    @Kevin: All of the terms in the snippet above refer to Unicode categories: "Letter, uppercase", "Letter, lowercase", "Letter, titlecase", "Letter, modifier", "Letter, other" and "Number, letter". Roman numerals are one example of a 'letter number'. See http://www.fileformat.info/info/unicode/category/Nl/list.htm – Joren Apr 27 '17 at 13:21
43

CLS compliance has to do with interoperability between the different .NET languages. The property is not CLS compliant, because it starts with an underscore and is public (note: protected properties in a public class can be accessed from outside the assembly). Although this will work if the property is accessed from C# it may not if it is accessed from other .NET languages that don't allow underscores at the start of property names, hence it is not CLS-compliant.

You are getting this compiler error, because somewhere in your code you have labelled your assembly as CLS compliant with a line something like this:

[assembly: CLSCompliant(true)]

Visual Studio includes this line in the AssemblyInfo.cs file which can be found under Properties in most projects.

To get around this error you can either:

  1. Rename your property (recommended):

    protected bool isNew;
    
  2. Set your whole assembly to be non CLS compliant:

    [assembly: CLSCompliant(false)]
    
  3. Add an attribute just to your property:

    [CLSCompliant(false)]  
    protected bool _isNew;
    
  4. Change the scope of the property, so that it can not be seen outside the assembly.

    private bool _isNew;
    
aolszowka
  • 1,300
  • 12
  • 36
Martin Brown
  • 24,692
  • 14
  • 77
  • 122
  • So, when you have a public property with a protected variable, what's the best convention? – Lilith River Aug 15 '11 at 14:46
  • 3
    Personally I like to make all fields private. If I need to increase the scope I would wrap it in a Property Get/Set. – Martin Brown Jul 31 '12 at 11:56
  • @MartinBrown: There are many situations where a class will have a public property whose setter calls a protected method which processes updates, but where derived types might have a legitimate need to use the field directly and post updates afterward (e.g. if a class derived from a control has a method to change both its color and caption, but the base doesn't, it may be helpful for the derived class to change both fields and then call the update method once). My inclination would be to use "Characteristic" and "_characteristic", since both VB.NET and C# accept it. What would you suggest? – supercat Jan 22 '15 at 17:18
  • @supercat: In my 13 years programming full time with .Net I don't think I can recall ever having needed to do that. But if I did I would go for a camelCase field name with no underscore. – Martin Brown Jan 22 '15 at 23:07
  • @MartinBrown: A field name which matched the property name except for case would not only be CLS compliant, but it would render the identifiers unusable in VB.NET. – supercat Jan 22 '15 at 23:18
  • @supercat it would not have to have the same name characteristicInternal for example. But really what you are suggesting breaks encapsulation. From the point at which you publish your code you can never be sure of the state of that field again. As such I would rather have another method or property setter that the child could use to do its update instead. – Martin Brown Jan 22 '15 at 23:52
  • @MartinBrown: Using a field will mean that the parent will have to rely upon the child to abide by its contract. Of course, parent classes have to rely upon derived children to abide by their contracts in other ways, so nothing new there. If a property is used, then unless the parent promises not to add new behaviors (in which case it may as well be a field) the child won't ever be sure what the parent is going to do with it. A lot really depends upon the extent to which the parent class exists to hide implementation *from the derived class*, versus the extent to which... – supercat Jan 23 '15 at 00:10
  • ...it exists to do things which derived classes could just as well have done by themselves without inheriting from the parent class, *were it not for the need to have derived-class instances be identifiable using base-class references*. If the contract for a base class is very specific about what it is supposed to do and how it is supposed to do it, there's not much point in trying to hide "implementation details" which don't have any flexibility anyhow. – supercat Jan 23 '15 at 00:18
28

The leading underscore concomitant with _isNew being visible (i.e., not private).

jason
  • 236,483
  • 35
  • 423
  • 525
  • 12
    +1 But you need to include the fact that the member is *non-private* which, along with the leading underscore, makes the member's name not CLS-Compliant. – Andrew Hare Jul 28 '09 at 15:57
7

The underscore causes the problem. Common practice is that the underscore is reserved for private fields. protected / public members should be properly cased and named.

For example:

public abstract class DomainObjectBase{   
   private bool _isNew;
   protected bool IsNew { get { return _isNew; } set { _isNew = value;} }
}

OR, if you want to use 3.x and get rid of the private field:

public abstract class DomainObjectBase{   
   protected bool IsNew { get; set; }
}
NotMe
  • 87,343
  • 27
  • 171
  • 245
2

A CLS-compliant identifier should not start with an underscore.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lloyd
  • 1,324
  • 7
  • 10
1

It's the underscore. See this article.

Tim Stewart
  • 5,350
  • 2
  • 30
  • 45
1

The leading _ is non-CLS compliant

Microsoft StyleCop will analyze your code, and provide links to the relevent documents explaining why it is not CLS compliant.

Frozenskys
  • 4,290
  • 4
  • 28
  • 28
  • 1
    I like the idea of StyleCop, but its rules conflict with FxCop rules, Resharper's reformatter and Visual Studio reformatter. – MatthewMartin Jul 28 '09 at 16:22
  • StyleCop and FxCop are both produced by Microsoft (although by different product teams) however I believe that StyleCop is the later, and therefore more preferred one if you wish to use a "Microsoft" code style. – Frozenskys Jul 28 '09 at 16:32
0

Because the name of the data member, _isNew, start's with an underscore.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
TcKs
  • 25,849
  • 11
  • 66
  • 104