Hi Bruce,
I hated the idea when a coworker introduced it, but now I'm all for it.
We're gradually converting our code over to using the "_" prefix for
member variables. Here's why.
Keep in mind that most of us are no longer writing code in text editors
and peering at printouts. Most of us are using Visual Studio and
Intellisense. I think that Hungarian Notation was a good idea for
assembly language, but it should have a stake driven through its heart
these days because if I want to know what type something is, I mouse
over it and VS tells me. So, there are now TWO considerations: the
written code itself, and the code within the Visual Studio environment.
With this in mind, we had an annoying problem when we followed what
appear to be MS's official guildelines. Given code like this:
public class Blah
{
private int foo;
public int Foo { get { return this.foo; } set { this.foo = value; }
}
}
and remembering that Intellisense is case-INsensitive, one can
immediately see why Intellisense has the annoying habit of choosing one
of this.foo or this.Foo "at random" when I type "this.f" from inside
the Blah class scope. This led to not a few bugs in our code, as touch
typists like me who often type without watching the screen would end up
with references to the property instead of to the member variable. I
lost count of how many infinite loops I introduced that way.
But I've already stated that I never use "this." unless I must resolve an ambiguity issue for the
compiler. It's pointless there, and you've also proven that it may be dangerous as well.
The "_" introduced two improvements. First, it's unambiguous when typed
in VS: "this._f" always means you want a member variable starting with
f, whereas "this.f" or "this.F" always indicates something public,
probably a property or method.
That's a good point if you're using "this." everywhere, which I know a lot of programmers do. I
don't because it's more typing and provides no real value, IMO.
Second, all member variables appear at the top of the list in the
debugger, so you don't have to go hunting for them.
Good, descriptive names and code layout alleviate the need to search for members based on their
member type in a large intellisense list.
Normally, just typing "f Ctrl+Space" is enough to find "foo", otherwise it probably shouldn't be
named "foo" in the first place. And even if it's unavoidable that "foo" will be difficult to find
using intellisense due to an overwhelming number of fields in a class, or other complexities, you
could also code like I do and group all private fields together. I've posted my layout snippets
after my sig.
Does it make the code or less readable on printout? Doesn't much matter
to me. It does, however, make VS easier to use, and since that's where
I spend most of my coding and debugging time, that matters a lot.
I agree that VS is more important than outside of VS since that's where the large majority of my
time is spent as well.
--
Dave Sexton
All of my structs and classes (components and non-components) use the following layout, so it's very
easy to locate the names of fields. As a matter of fact, I often have the Private / Protected
region expanded when I'm coding methods so I don't have to browse through a long list of fields in a
complex object. I'm sure that helps me locate unknown field names much faster than browsing a list
of members that all begin with "_".
(Watch for tabbing issues if anyone tries to use the snippets since I pasted them here and the
formatting was probably lost)
{ layout.snippet }
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="
http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>layout</Title>
<Shortcut>layout</Shortcut>
<Description>Code snippet for region layout of code files</Description>
<Author>Dave Sexton</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal Editable="false">
<ID>class</ID>
<Function>ClassName()</Function>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[#region Public Properties
#endregion
#region Private / Protected
#endregion
#region Constructors
/// <summary>
/// Constructs a new instance of the <see cref="$class$" /> class.
/// </summary>
public $class$($end$)
{
}
#endregion
#region Methods
#endregion
#region Events
#endregion
#region Event Handlers
#endregion
#region Nested
#endregion]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
{ layoutc.snippet }
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="
http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>layoutc</Title>
<Shortcut>layoutc</Shortcut>
<Description>Code snippet for region layout of code files that contain a class that can be edited
in a designer (derived from Component)</Description>
<Author>Dave Sexton</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal Editable="false">
<ID>class</ID>
<Function>ClassName()</Function>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[#region Public Properties
#endregion
#region Private / Protected
$end$
#endregion
#region Constructors
/// <summary>
/// Constructs a new instance of the <see cref="$class$" /> class.
/// </summary>
public $class$()
{
InitializeComponent();
}
#endregion
#region Methods
#endregion
#region Events
#endregion
#region Event Handlers
#endregion
#region Nested
#endregion]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>