How do I disable the implicit "this" in C#?
Asked Answered
G

12

9

This bothers me a lot and I find I write stupid bugs when combined with Intellisense (VS 2008 Pro):

class Foo
{
    public Foo(bool isAction)
    {
        this.IsAction = IsAction;
    }

    public bool IsAction { get; private set; }
}

Did you catch it? I certainly didn't until IsAction never changed, causing bugs.

Intellisense somehow converted "isA<tab>" to "IsAction" for me which means the property Foo.IsAction is always false regardless of the constructor input. Just brilliant.

I have to say that I particularly hate the "implicit this" (I don't know if that has a formal name) and I would like to turn it off so it never assumes it. Is there a way to do this? This also applies in calling static methods of the same class.

Alternatively, what naming conventions avoid this little problem? The property must remain "IsAction" so it has to be a convention on the constructor parameter name. Oddly enough, if I name it with the exact matching spelling then this.IsAction = IsAction; works out correctly.

The problem isn't case-sensitive languages but the implicitness of this. Now that I think about it, this also more of a VS 2008 Pro question than a C#. I can live with code already written without the this but I don't want to write new code without it which means telling In


Noldorin's answer got me thinking.

Now that I think about it, this also more of a VS 2008 question than a C#. I can live with code already written without the this (though I do change it if I'm in there mucking around) but I don't want to write new code without it which means telling Intellisense to stop doing it. Can I tell Intellisense to knock it off?

Geopolitics answered 5/6, 2009 at 19:41 Comment(4)
This is not a problem of this implicitness. Even If you could turn that off (I think you can't), I'm sure you would turn it on again in a few minutes.Centesimo
I'm pretty sure I wouldn't. Did I mention I hate it? :)Geopolitics
I'd love to see your code without it, every call to a private or protected method preceded by "this"... Good classes contain many small refactored and expressive methods to achieve their goal. You would be filled with "this" all over the place.Centesimo
excuse me for being a newbie programmer here but there is nothing wrong with your code as far as I can see except that the variable you're passing and the one you're assigning are different. Case sensitivity being the demon I can see here.Deprivation
P
3

This is a common problem. Microsoft has some recommendations for parameter names but they aren't terribly helpful in your case.

As other responders have mentioned, you cannot "disable" the C# language scope resolution behavior - your best approach is a naming conventions. Others have mentioned "Hungarian" notation - some people have a knee-jerk reaction to this because of the confusion over the original intent of the notation.

My personal approach, has been to use the character 'p' as a prefix to parameter names of public functions. It's unobtrusive, simple, readily identifiable, and easy to enforce with tools like Resharper.

The particular naming convention you choose is a matter of preference and style; however, there is some benefit from being consistent in the practice you select.

Using my suggested naming convention, you would write your constructor to:

class Foo
{
    public Foo(bool pIsAction)
    {
        this.IsAction = pIsAction;
    }

    public bool IsAction { get; private set; }
}
Parabola answered 5/6, 2009 at 20:13 Comment(1)
Parameter names are part of the interface, visible to callers. You might find a convention for member fields would be better.Mireyamiriam
R
6

I've just tried your code in Visual Studio 2008. Turning on the in built static analysis yields the following error:

Warning 3 CA1801 : Microsoft.Usage : Parameter 'isAction' of 'Foo.Foo(bool)' is never used. Remove the parameter or use it in the method body.

My suggestion is by turning this on you will find errors like this early on. To enable this choose properties from the context menu on the project, then select the Code Analysis tab and select "Enable Code Analysis on Build"

Ryley answered 5/6, 2009 at 20:45 Comment(0)
P
4

You could always go back to Hungarian notation [I'm preparing to get flamed as I type this]. If you can deal with the ugliness, it would solve your problem. This is a suggestion, not a reccomendation.

Alternately, I'm pretty gosh darned sure that static code analysis will catch this and warn you about it. Try FxCop.

EDIT

I have been using Resharper for over a year now, and I do know that it is very smart about assisting you in a case sensitive way. Among other benefits, your intellisense problem will be solved by installing Resharper.

EDIT 2

I just checked. Neither FxCop, nor Resharper catches this error directly. What both do catch is the fact that the isAction parameter is unused in the Foo method. In this case, the warning would clue you in to the mistake. In cases where the parameter is used in another way within the method, it might slip through static code analysis.

Puff answered 5/6, 2009 at 19:46 Comment(8)
I knew event he mention of Hungarian notation (even though I didn't recommend it) would elicit downvotes. :)Puff
Yes, but the suggestion of static code analysis got a +1 from me ... it would have caught this :-)Significant
Please, no Hungarian notation! I'm not sure why you've mentioned it if you don't recommend it.Madeline
Systems Hungarian (where you indicate things like 'count' or 'index' not 'int' or 'long' in the variable's name - see msdn.microsoft.com/en-us/library/aa260976(VS.60).aspx) seems quite useful to me, and if it helps you control the environment better, then why not? (I have to say the thought of using of using Apps Hungarian annoys me - redundancy like that really gets my dander up.)Gaseous
StyleCop should catch this - if you're willing to put up with it!Youngster
Mentioned it, because it's a possibility. I'd certainly prefer that over automatically prefacing all instance members with "this." Which is not to say I'd prefer either.Puff
I'm not sure that using hungarian would help here (and I'm generally a fan of it)... because you'd end up renaming both the property and the parameter, and they'd probably still differ only in their case! Also, it's "Application Hungarian" you're talking about, not "Systems Hungarian" (see en.wikipedia.org/wiki/Hungarian_Notation).Sidonnie
I would suggest you only use Hungarian for your code's innards. Leaking notation into your public API is bad practice. In that case, IsAction stays IsAction, and isAction becomes blnIsAction. If you implement a backing field for IsAction, it becomes mblnIsAction, or m_blnIsAction... Wow, writing those variable names just made me feel dirty. Ick.Puff
P
3

This is a common problem. Microsoft has some recommendations for parameter names but they aren't terribly helpful in your case.

As other responders have mentioned, you cannot "disable" the C# language scope resolution behavior - your best approach is a naming conventions. Others have mentioned "Hungarian" notation - some people have a knee-jerk reaction to this because of the confusion over the original intent of the notation.

My personal approach, has been to use the character 'p' as a prefix to parameter names of public functions. It's unobtrusive, simple, readily identifiable, and easy to enforce with tools like Resharper.

The particular naming convention you choose is a matter of preference and style; however, there is some benefit from being consistent in the practice you select.

Using my suggested naming convention, you would write your constructor to:

class Foo
{
    public Foo(bool pIsAction)
    {
        this.IsAction = pIsAction;
    }

    public bool IsAction { get; private set; }
}
Parabola answered 5/6, 2009 at 20:13 Comment(1)
Parameter names are part of the interface, visible to callers. You might find a convention for member fields would be better.Mireyamiriam
F
2

FxCop will complain about this because the isAction parameter is never used. Specifically it will pull rule CA1801:ReviewUnusedParameters.

Personally I've always felt that the C# compiler should give a warning about unused parameters.

Flirt answered 5/6, 2009 at 20:3 Comment(0)
M
1

I'm afraid there's no way to disable the "implicit this" feature. It's part of the language specification and compiler, and there's no way to turn it off.

Personally, I don't consider this a big problem. Admittedly, it is important to be careful with the capitalisation of member and parameter names, but this is always the situation in a case-sensitive language such as C#.

My recommended "solution" (which you already seem to be doing) is to always use the this keyword for referencing properties/fields, so that it should immediately stand out when you should be using a parameter. It's not going to solve the problem for you, but if you keep it in mind it will undoubtedly help. Just getting in the habit of this (as well as remembering all parameter/local variable names should start with lower-case) will do you well to avoid this issue in the future.

Madeline answered 5/6, 2009 at 19:47 Comment(4)
I was going to comment but I'm going to amend my question instead here in a second.Geopolitics
So you want to disable intellisense suggestions for all properties as far as I understand? I'm pretty sure this isn't possible, but I'll have a think about it.Madeline
I want it to not pull in the implicit class members, namely instance, but static would be fine too.Geopolitics
@Colin: Yeah, I think I see where you're coming from now. The problem boils down to the fact that C# is case-sensitive but VS Intellisense is not. In my opinion, Intellisense really should be case-sensitive, at least on the first character. I can't think of a good solution to this however. Would simply disabling the Intellisense completion list be acceptable to you?Madeline
S
0

This gets me all the time. I've taken to prepending variables being passed into the constructor with a '_', like:

class Foo
{    
    public Foo(bool _isAction)
    {
        this.IsAction = _isAction;
    }
    public bool IsAction { get; private set; }}
Stillborn answered 5/6, 2009 at 19:46 Comment(5)
Usually, the underscore is reserved for indicating an instance variable, not a parameter. Using it to indicate a parameter should be just fine, but might be frustrating for developers not familiar with your convention.Puff
If I don't do auto-properties then I name my property "IsAction" and my backing field "_IsAction" so that convention won't work for those. :)Geopolitics
I've seen that before too, but it's horribly ugly. It's an acceptable practice for naming private fields (and even used by Microsoft at times), but certainly not for parameters.Madeline
I don't like it either, but current company coding standards prohibit the '_' everywhere else, so it sorta kinda works. The key is to get the name of the parameter different than the name of the property.Stillborn
The problem with this solution is you simple don't see parameters going into methods in the BCL with an underscore- making your style inconsistent with everybody elses.Ryley
B
0

It's an annoying problem in Visual Studio's intellisense. Resharper gets it right most of the time though.

Blagoveshchensk answered 5/6, 2009 at 19:51 Comment(0)
A
0

I think it's more likely that the developer picked "IsAction" instead of "isAction" from Intellisense. I don't think Intellisense would change "isA" to "this.IsAction".

If the names differ only by case then I think the only way to prevent mistakes like this is by being aware of them and careful, and by using unit tests effectively.

Amazed answered 5/6, 2009 at 19:51 Comment(5)
Yes, because in this case, it would default to the more specifically case match (ie. the isAction argument) in the default VS intellisense. this was user error ;-)Significant
If you get down to it then bugs derived from developer errors. Saying a developer error caused a bug is redundant and not helpful to my question in the slightest. I am looking for a way to curtail those errors to avoid the bugs.Geopolitics
This is going to work in C# ;). And also, properties should always start with a capital letters (even code analysis will tell you that if I'm right). The same goes for functions in your code... it should always start with a capital letter.Pneumatograph
@Colin -- see the 2nd sentence in my answer. If the names differ only by case there's not much that Intellisense can do to prevent the mistake. A good unit test would catch it.Amazed
@Jamie Ide, in a way, that's the ultimate solution, isn't it? Adhering to TDD principles would mean you first write it to fail, then implement the feature. Seeing it fail first would ensure that you know when to stop (when it succeeds), and therefore you never assume it works without verifying.Puff
C
0

It might be annoying in other capacities, but you could turn off the option to have Intellisense pre-select the most recently used member. I realize that won't really fix the problem outright but it might possibly help prevent some accidental tabs when you don't really have the right item selected.

Conjecture answered 5/6, 2009 at 19:54 Comment(0)
I
0

Note:

If you are using Resharper, you have some shortcuts that write a lot of this code for you and avoid the error.

You can either create the property first, then hit Alt-Ins and choose "generate constructor", or you can add a parameter "isAction" to the constructor, hit Alt-Enter with the caret in the parameterName, and choose the "Create and initialize Auto-property IsAction" action from the menu that pops up.

Interlink answered 5/6, 2009 at 20:11 Comment(1)
Another favorite of mine is when you have members with long names. I use intellisense to find IsAnotherActionThatIsVeryLong by typing IAATIVL, and isAnotherActionThatIsVeryLong by typing iAATIVL. I never knew I was missing it until I had it.Puff
Y
0

Things have changed since 2009 when these other answers were submitted. I see the question is tagged visual-studio-2008 but this may still help someone. In recent versions of Visual Studio, such as Visual Studio 2019, it's possible to configure the IDE to check C# code for code-style conformity. One of the available checks is to require the explicit use of this.

Go to Options > Text Editor > C# > Code Style > General, where you'll find a group named 'this.' preferences. Set each one to Prefer 'this.' and set the Severity to Error.

Code style options in VS2019

Any violations in your C# code will cause a code-style-check error to be shown in the IDE. Curiously though, this doesn't cause the build to fail.

Code style errors in VS2019

See also the documentation on the EditorConfig file format, where the relevant parameters are named like dotnet_style_qualification_for_field.

Yanyanaton answered 15/8, 2020 at 12:32 Comment(0)
G
0

Further ideas are:

  1. Implement your own checker, e.g. by searching for the regex \b(\w+)\b\s*=\s*\1. This will find all self-assignments, not only in class constructors. It is not theoretically fool-proof (e.g. it won't capture self-assignments with a /**/ comment mixed into the middle of them), but it should work well enough in all practical scenarios.

  2. If you don't mind a little bit of extra typing you can initially give the constructor parameter a different name and rename it after writing the body of the constructor.

Gleeful answered 15/8, 2020 at 19:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.