TheChaseMan's Frenetic SoapBox

Always looking for better ways to do things...

Naming Conventions, CLSCompliantAttribute, Underscores, etc

When I attended Guerrilla .NET a few years ago at DevelopMentor, Mike Woodring and Keith Brown were showing examples to the class using the underscore prefix for private class field names. It was a cool trick that the Microsoft developers were using internally at the time. I've adopted that practice, and if you look at the framework code using Reflector, you can see the underscore prefix (and "m_" in some cases) for private variables. For the record, I have been watching the Designing .NET Class Libraries videos as they are released on the Microsoft .NET Framework Developer Center. I'm not 100% confident, but I think Brad Abrams mentioned that they do not use underscores at all anymore, but he seemed reluctant to tell developers how to name local or private variables. Either way, I'm trying to do the right thing.  :-)

Anyway, here's a couple of interesting notes. First, using the underscore prefix is not CLS compliant, so you definitely shouldn't use them for public or protected fields. In fact, you shouldn't even have public or protected fields if you can avoid it. Here's a quote a comment posted by Brad on Kevin Dente's blog:

"Well, not excatly what you are looking for, but one fix here is to not have any public or protected fields. There is just no reason to expose those. You can always use a property to abstract them. That will save your butt some day when you change some implementation details without breaking client code."

If you decide to ignore this rule and create a protected field for example, and then expose a public property for it later, you can run into problems if you camel-case the protected field name and Pascal-case the public field name using the same name. For example, Visual Basic is not case-sensitive so it can't tell the difference:

public class Foo

{

      protected int bar;

 

    public int Bar

    {

        get{return this.bar;}

        set{this.bar = value;}

    }

}

 

Public Class FooDerived : Inherits Foo

    Public Sub SomeMethod()

        ' problem, this accesses property set

        ' because VB is not case sensitive

        Me.Bar = 1

 

    End Sub

End Class

Of course, you will get a compiler warning about this if you build the project containing the Foo class with the CLSCompliant attribute on the assembly. This means that using the same name for a protected field and property name (despite the case difference) is not CLS compliant. Using the CLSCompliantAttribute is not the default in a C# project, nor do I talk to many C# developers that think to include that attribute. Seemed worthy of a note.


Digg!

posted on Saturday, February 19, 2005 9:18 AM

Feedback

# re: Naming Conventions, CLSCompliantAttribute, Underscores, etc 3/4/2005 12:33 PM Ron Murphy

"Don't us protected fields..." argument? Why, not?

'I want to use this (get/set)
'in my derived classes
'but not in consumers
Protected _myThing As Thing = New Thing()Public Readonly Property MyThing As Thing
Sub Get()
Return _myThing
End Sub
End Property

...or maybe...
Public Property MyThing As Thing
Sub Get()
Return _myThing
End Sub
Sub Set(Byval Value As Thing)
If Not _myThing.Equals(Value) Then
'Do stuff I want to happen when
'consumer changes property
_myThing = Value
Me.DoStuff()
End If
End Sub
End Property

So, I use some non-CLS complient naming for my protected field, or give protected/public different names:
Protected InnerThing As Thing
Public Readonly Thing As Thing
Sub Get()
Return Me.InnerThing
End Sub
End Property

# re: Naming Conventions, CLSCompliantAttribute, Underscores, etc 3/6/2005 10:30 AM Sean Chase

If you use a non-CLS compliant name for a protected field, what happens to a class that derives from your class? That's the problem. That's how protected fields are exposed, and that's why the naming conventions are important. Also, the same argument for using protected properties instead of fields apply with respect to public fields. Implementation changes are not breaking changes.