.NET naming conventions and protected members

While I've been doing a bunch of .NET development over the last year, I haven't really developed any class libraries until now (been web services and web application stuff, mostly). Being a good .NET citizen, I set the CLSCompliant attribute. I was coding merrily along, using the C# coding standard that I've adopted - camel case for members, Pascal case for properties and methods. Everything was ducky until I tried to add a protected field and a corresponding public accessor property. The compiler complained that this wasn't CLS compliant, since case-insensitive languages like VB.NET can't differentiate between the starts-with-lower-case field and the corresponding starts-with-upper-case property. Doh! Not sure why I never thought of that. The .NET framework style guide recommends camel case for protected fields, but I guess they didn't consider the case where there's a corresponding public property when they wrote that recommendation.

My first thought was to switch to the other common style that I've seen (but that I've never been crazy about) - prefixing fields with an underscore. No love - that's also not CLS compliant. My next thought was - what does Microsoft do in the framework classes? I poked around the Rotor source code site, trying to find an example. Guess what? Couldn't find one. The only protected members that I found were either internal or had no corresponding public property. The majority of the fields that I looked at were simply declared as private with a public accessor property.

Now, this was hardly a comprehensive search - I just picked several files at pseudo-random (trying to pick files that would have reasonably substantial code in them). I haven't downloaded the full Rotor source and searched. But that said, I thought it was kind of interesting that there wasn't a single example to be found. The style guide says that a protected instance field is "rarely used", and I get that. The only reason I can envision using one is in performance sensitive code where you don't want a deriving class to incur the overhead of a property accessor. Pretty obscure. So I'm going to stick with the private field, public/protected property model.

As a final note, in poking around the Rotor source it seems that the Microsoft developers mostly used three different coding styles for fields - camel casing, leading underscore, and the old Hungarian style "m_". I wonder if they've settled on one style going forward.

I also wonder if I should just get a life and stop spending so much time thinking (and blogging) about stuff like this.

3 Comments

  • When we were doing our coding standards for C# we came across this problem. We had a bunch of internal MS people pinged to see what they did. The result was there was no standard, apart from just using case in-sensitive fields.



    We decided against that in-case we had some VB.Net development.



    We now use m_, which works OK, but is not ideal.

  • A clarification on what Brad said: you use protected properties, instead of fields. This is the standard in .net and I it is in the guidelines as well.



    As he said, you should not allow the public to ever see a field. It just causes problems.

  • Assuming you have valid reasons for needing protected fields, there actually are two CLS-compliance issues which led us to settle on using m_:



    1) We elminated using camel/pascal casing to differentiate protected fields and public properties since protected fields and public properties of the same name, varying only by case, are not CLS compliant. Therefore, if you use pascal casing for a property (e.g. Foo) and camel casing for the protected field (e.g. foo), you will not be CLS-complaint, and therefore your component can not be used by some CLS-compliant languages (such as Visual Basic .NET in this case).



    2) We eliminated preceeding fields with an underscore, since protected fields with an underscore (e.g. _foo) are also not CLS-complaint, thus may be inaccessible by some CLS-compliant languages (although happens to work fine with C# and VB .NET)



    Therefore, we settled on m_ for fields, since this works for protected fields as well, assuming you have protected fields.



Comments have been disabled for this content.