ailon's DevBlog: Development related stuff in my life

What's Wrong with this?

5/29/2008 9:55:30 AM

Every time I read a C# book or an article or just a code sample in MSDN I can't stop wondering why don't people (and by people I don't mean just average Joe's but respected authors, MSDN documenters, etc.) use this qualifier unless it's absolutely required to distinguish between identically named local variables and object fields?

I use this all the time and I think it's way easier to understand your own code. And don't get me started on someone else's code. Let me show you an example.

Yesterday I was implementing a SiteMapProvider for a project I'm working on. I looked  at the sample in MSDN. The main "meat" is in BuildSiteMap method. I'll paste it here in full. It's a little long but that's exactly the point.

// Build an in-memory representation from persistent // storage, and return the root node of the site map. public override SiteMapNode BuildSiteMap() { // Since the SiteMap class is static, make sure that it is // not modified while the site map is built. lock (this) { // If there is no initialization, this method is being // called out of order. if (!IsInitialized) { throw new Exception("BuildSiteMap called incorrectly."); } // If there is no root node, then there is no site map. if (null == rootNode) { // Start with a clean slate Clear(); // Select the root node of the site map from Microsoft Access. int rootNodeId = -1; if (accessConnection.State == ConnectionState.Closed) accessConnection.Open(); OleDbCommand rootNodeCommand = new OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL", accessConnection); OleDbDataReader rootNodeReader = rootNodeCommand.ExecuteReader(); if (rootNodeReader.HasRows) { rootNodeReader.Read(); rootNodeId = rootNodeReader.GetInt32(0); // Create a SiteMapNode that references the current StaticSiteMapProvider. rootNode = new SiteMapNode(this, rootNodeId.ToString(), rootNodeReader.GetString(1), rootNodeReader.GetString(2)); } else return null; rootNodeReader.Close(); // Select the child nodes of the root node. OleDbCommand childNodesCommand = new OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?", accessConnection); OleDbParameter rootParam = new OleDbParameter("parentid", OleDbType.Integer);
rootParam.Value = rootNodeId;
childNodesCommand.Parameters.Add(rootParam); OleDbDataReader childNodesReader = childNodesCommand.ExecuteReader(); if (childNodesReader.HasRows) { SiteMapNode childNode = null; while (childNodesReader.Read()) { childNode = new SiteMapNode(this, childNodesReader.GetInt32(0).ToString(), childNodesReader.GetString(1), childNodesReader.GetString(2)); // Use the SiteMapNode AddNode method to add // the SiteMapNode to the ChildNodes collection.

// LOOK HERE
AddNode(childNode, rootNode);
// LOOK HERE

} } childNodesReader.Close(); accessConnection.Close(); } return rootNode; } }

I've highlighted one line in the method:

AddNode(childNode, rootNode);

By glancing at that line could you tell me right away is rootNode a local variable or a field of the object? Wouldn't it be much more obvious if it was

AddNode(childNode, this.rootNode);

We loose readability by omitting this so we must gain something in return, right? What are we gaining? Do I miss something other than saving 5-10 bytes in source file and 5 extra keystrokes? And the keystroke argument isn't always true.

Suppose you have a class defined like this:

class test
{
    public XmlNode XmlNodeHolder;
    public test()
    {
        XmlNodeHolder = null;
    }
}

To type that XmlNodeHolder in the constructor with the help of IntelliSense I had to press 8 keys (x-m-l-n-o-d-e-h) before I got the right line in IntelliSense. Now I would use this

class test
{
    public XmlNode XmlNodeHolder;
    public test()
    {
        this.XmlNodeHolder = null;
    }
}

I could type this.XmlNodeHolder in 4 key presses (t-h-.-x). So the only argument that I see and can't argue with is saving bytes in the file. But who cares about 10 bytes in the source file these days? 100 bytes? 1kb anyone?

So either I miss something important in functionality, performance or something else or I just can't understand the trend.

kick it on DotNetKicks.com

Tags: ,

Comments

5/29/2008 1:57:06 PM

Tr3v

I completely agree I always use the this keyword.

Tr3v United Kingdom

5/29/2008 5:21:26 PM

Will

I used to do the this. thing all the time to bring up intellisense.  Now I just ctrl-j.

Will United States

5/29/2008 5:31:33 PM

ailon

@Will: So what? I'm not using this. to bring IntelliSense up. In my last example you have several items in IntelliSense starting with XmlNode... before the XmlNodeHolder if you don't use "this."

ailon Lithuania

5/29/2008 6:37:47 PM

Pierre

You don't have to use "this" to show that a name is a class member... if you give your class members the right name ;). That is, begin all your class member names by "m_" or "_".

I can't imagine a program where class members are named the same way as local variable (ie you can't make the difference between a local variable and a class member at first glance). How could you maintain or modify such code?

MSDN samples are not good programming practices. Microsoft warns you: "This sample code is provided to illustrate a concept and should not be used in applications or Web sites, as it may not illustrate the safest coding practices." ;)

Pierre France

5/29/2008 6:40:30 PM

Julien

you could also have the same result by using an "_" or any other prefix for your private members. I prefer it because you can more easily differentiate between private members and properties. For instance, this.status and this.Status look almost the same. _status ans Status don't.

By using a "_" you also reduce:
- the overall noise (specially because this is a keyword by default, so it's displayed like flow keywords (if, for, while, return, etc.)
- the number of choices in intellisense. if you start typing _ you'll only have private members, whereas "this." will suggest everything that is accessible
- a few keystrokes

And finally, when using a "_", all the private members are grouped in the debugger view at the beginning of the tree node.

Julien France

5/29/2008 7:02:42 PM

Steve

I'm with you 100%, brutha. Power to 'this'!

Steve Canada

5/29/2008 7:07:48 PM

CrashCodes

I believe fxCop and maybe even Visual Studio will give "redundent" warnings when this is used unnecessarily. Now why that is a warning I'm not exactly sure, but it discourages the use of "this".

This example failed to follow the convention (from Microsoft no less) that private fields are prefixed with "m_" or "_" which would be a less verbose way to acquire the same readability as "this.".

CrashCodes United States

5/29/2008 7:09:17 PM

Damien Guard

Because if you use "this" all the time the code soon becomes a longer to scan.  It's just visual noise.

If you keep your methods short and declare your variables close to where they are used then you don't need "this" at all as the local variable declaration will be on-screen at the same time.

The only thing worse than seeing this everywhere is seeing if (boolean == true) and if (boolean == false) :p

[)amien

Damien Guard United Kingdom

5/29/2008 7:10:23 PM

gerrod

Kudos to the underscore folks:

  AddNode(childNode, _rootNode);

You shouldn't use "this" as a workaround for badly named fields. Another argument would be that in C# 3.0, you generally use AutoProperties in favour of fields; hence:

  AddNode(childNode, RootNode);

gerrod United Kingdom

5/29/2008 7:12:25 PM

beefarino

I find that using either a name prefix or this. to disambiguate local vs. member variables works fine, provided that the chosen practice is used consistently by each developer and across the team.  

It's not doing any disambiguation - as in the cited code - that causes an issue for me.

beefarino United States

5/29/2008 7:51:20 PM

Josh Schwartzberg

Maybe we should consider always use the full namespace when referencing a type as well?

Josh Schwartzberg United States

5/29/2008 7:51:23 PM

Tim C

I always do _privateField or _PrivateField and PublicField or PublicProperty. Then I do localVariable.

Tim C United States

5/29/2008 8:06:20 PM

SuperJason

My vote is for the underscore. Simple, and doesn't add a lot of noise.

SuperJason United States

5/29/2008 8:16:23 PM

Jon von Gillern

I much prefer to use a "_" to differentiate my fields. Although, I do use "this" sometimes when I have a lazy loaded property or the getter/setter modifies calls other code (to fire events, etc)

Jon von Gillern United States

5/29/2008 8:27:48 PM

Greg

I understand the argument for underscores, it works.  Personally, I use "m_"  Fields don't need to have "this" if they are named correctly.  However, what about methods and properties?  I use "this" on both.  It clearly defines when a method or property is either inherited or within this class.  Frequently, properties/ methods names can look like class names.  Adding this makes it easier to quickly identify where the method/property is coming from.

Generally, the development community is recommending to use properties in your class over fields; hence the movement to AutoProperties referenced by "gerrod".  With that in mind, the "_" or "m_" naming convention is shot.  

Greg Canada

5/29/2008 8:38:14 PM

Eric Schneider

Also If you decide to refactor and make it Static/Shared, you will need to remove them all. I prefer m_ myself.

Eric Schneider United States

5/29/2008 8:49:24 PM

John

I use both "this." and an underscore (_). For example:

this._privateField = ...

I agree with all the reasons mentioned above for using the underscore. I use "this." because I'm a visual person and I like the blue code coloring. I can easily scan for a blue "this" to see where the state of the class is being accessed or modified.

John United States

5/29/2008 8:52:32 PM

Edward Poore

Again I agree with you, I actually spend time going through code that I'm going to use (if brought in from somewhere else) and type out all these this.'s.

Edward Poore United Kingdom

5/29/2008 9:47:18 PM

Travis

Resharper > this.

Travis United States

5/29/2008 10:07:00 PM

Nick

"By glancing at that line could you tell me right away is rootNode a local variable or a field of the object?"

Yes.  Eclipse at least will have different syntax highlighting for local variables and fields.

Nick United States

5/29/2008 10:52:04 PM

Jim

There are so many other things wrong with this code it seems wrong to pick on the this (non)issue.  The interface of the class is lousy, requiring <constuctor> + Ininitalize() + BuildSiteMap() to be called in that order, or the RootNode property is not in a good state.  The function under question is too long.  It does too many things.

If the code were factored into a decent OO style, (1) it would become obvious whether 'rootNode' was local or a memeber, (2) the question would never come up.

Coding standards and conventions are like good handwriting, they make it easier to read, but they won't help you understand something that's poorly structured.  _ or m is easier to do than writing code that's obvious, but it's a poor substitute.

Jim United States

5/29/2008 10:57:42 PM

esbium

Using _ and m_ for variables names is an old naming scheme developers used before we had the powerful IDE's that we have today.  I really see no reason for it in today's world of VisualStudio and Eclipse/Netbeans/Intellij.  I also vote that more people should use the "this" keyword!

My 2 cents!

esbium United States

5/29/2008 11:57:51 PM

Ricky Clarkson

I think you're onto something here.  Hey, actually, I sometimes forget what type my variables are too, so we should have a language where you have to include the type on every single use of a variable.  Something like:

int y = (int x) * (int x) + (int z);

Wow, super-readable.

The above is sarcasm.  Keep your classes small and focused and this isn't a problem.  You don't even need IDEs to make it not a problem.

Ricky Clarkson United Kingdom

5/30/2008 12:25:04 AM

kevin

adding both _ and this. are useless noise unless you are trying to read your code in notepad or are color blind.  Use a modern editor and member variables appear a different color.  Honestly, manually adding things to make things visually distinctive is dumb when if you have any type of decent editor it will do it for you.

kevin United States

5/30/2008 8:53:43 AM

ailon

About color-coding:

1. I see several comments here suggesting that you can see member fields in different color in "modern" IDE's. Is VS2008 not a modern IDE or could you, please, tell me where can I turn this feature on? I scanned the list of color-coding settings in Options but couldn't find anything like this.

2. Not all articles/blogs color-code their samples, MSDN Library 2005 had no color-coding (I believe 2008 has since it's color-coded online) and I haven't seen a color-coded book yet. And anyway the mentioned special color-coding for member fields is not a common thing. Actually I heard about it here for the first time and it's a really nice and simple idea.

ailon Lithuania

5/30/2008 12:01:59 PM

Andrew

Take a look at the http://www.jetbrains.com/resharper - this "must have add-in" adds a lot of usefull additional color settings to standart VS2005/2008 "Font and Color" dialog.

Andrew

5/30/2008 3:42:39 PM

configurator

I hate the 'this.' keyword.
It produces visual noise and makes code unreadable and unmaintainable.

Well, I don't really, but at my workplace it is used *way* too much.
we have some design pattern where many (most) of our classes have the same properties (InputParameters, OutputParameters, and more).
The usage of 'this.InputParameters', 'this.OutputParameters', etc. is horrendous and makes many of our functions completely undreadable.

Instead of having a function
void Calculate() {
OutputParameters.Total = InputParameters.Input1 + InputParameters.Input2 + InputParameters.Input3;
// The names have been changed to protect the innocent
}

We have
void Calculate() {
this.OutputParameters.Total = this.InputParameters.Input1 + this.InputParameters.Input2 + this.InputParameters.Input3;
// The names have been changed to protect the innocent
}

Is this more readable in any way?

I think this. should be used in moderation:
- Not where a design pattern means almost all of your classes have the same property.
- Not where the variable is named m_something.
- Also, I prefer using 'this.' on method calls only when they are not defined in the same file. That way a clear distinction exists between what is actually mine (and has an implicit 'this.') and what is inherited or external is any way (and requires an explicit 'this.' like extension functons).

configurator Israel

5/30/2008 4:05:34 PM

Alvin Ashcraft

I use the underscore for local members. I think it's easier to read. Unnecessary 'this' keywords add clutter to the code IMO.

Alvin Ashcraft United States

5/30/2008 4:12:38 PM

ailon

@configurator: sure, using "this." just because you can is in no way better than not using "this." just because you can.

ailon Lithuania

5/30/2008 5:48:46 PM

Jane Dallaway

I've just downloaded and started working with StyleCop [blogs.msdn.com/.../...crosoft-source-analysis.aspx].  
The rule "SA1101: The call to m_source must begin with the 'this.' prefix to indicate that the item is a member of the class." covers just this scenario.  Previously I've used m_ notation, but am happy to move to a more accepted method.

Jane Dallaway United Kingdom

5/30/2008 6:10:43 PM

Randolpho

This will probably end in a flame war -- everybody is different and everybody thinks their way is the best way.

I don't think there's any right or wrong answer to this. (heh) My own personal opinion is that rootNode would be more obvious as a member variable if it were PascalCase rather than camelCase. My code style reflects that... all member names, regardless of access qualification or type, are PascalCase, all local names are camelCase. The only variance I allow to that is for property backing fields, which I prefix with an underscore, i.e. _MyProperty is the backing field for the property MyProperty. Although lately I've been experimenting post-fixing with the word Value (i.e. MyPropertyValue is the backing field for the property MyProperty) and have been at least as happy with it as I am with an underscore prefix.

Anyway, my point is that it's a stylistic issue. No one style is better than another in terms of readability because anyone expected to read the code should also be expected to investigate the scope of a variable when they encounter it. If they happen to be reading the code in a modern IDE like Visual Studio, this is as easy as hovering over the name with the pointer/cursor.

Randolpho United States

5/30/2008 6:14:13 PM

Randolpho

Damien Guard wrote:
The only thing worse than seeing this everywhere is seeing if (boolean == true) and if (boolean == false) :p

Heh... with nullable types, you're gonna be seeing things like if(nullableBoolName == true) a heck of a lot more often.

Randolpho United States

5/30/2008 11:27:57 PM

Sam

Yes, underscores are the best. I think visual studio should even force the members to be underscored. Good post though and it shows you are thinking carefully Smile

Sam United States

5/30/2008 11:41:25 PM

faceup

How about public variables? You still want to diff them from local variables, right? So this covers both private and public cases.

faceup United States

5/31/2008 7:55:48 AM

bryan

Technically, I think the only time you need to use "this" is when you need to differentiate between "this" and "base".

bryan Canada

6/2/2008 3:59:35 PM

ahura mazda

Simple.

If you have a coding style in place:

'rootNode' will be a local variable/parameter
'_rootNode' will be a class level variable
'RootNode' will be a property

no need for "this".

ahura mazda United Kingdom

6/2/2008 8:23:41 PM

Prodis

I always use this this keyword when I referrer to member instance, including methods.
The major of my co-workers don't agree and don't use the this keyword like me.
I agree with your opinion, the this keyword leaves the code more readable.
It costs nothing type the this keyword in the code, at last we write code every day and we have practice in this.

Hugs.

Prodis Brazil

11/26/2008 7:21:16 AM

Andrew

You can remove "this" to show that a name is a class member.

Andrew United States

2/17/2009 5:21:44 AM

Replica Ordnance

simply put. People are lazy. Why put 'this' when you don't have to. Smile

Replica Ordnance Australia

2/17/2009 2:57:04 PM

Avanta Meeting rooms

From a developers POV,technically, I think the only time you need to use "this" is when you need to differentiate between "this" and "base".

Avanta Meeting rooms United Kingdom

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading



Copyright © 2003 - 2010 Alan Mendelevich
Powered by BlogEngine.NET 1.5.0.7