> I've had coworkers who would put this before every method call, because...? When calling your own method, in your own class, that inherits/implements no other classes, why on earth would you decorate your own method call with this?
I do this all the time, and I didn’t know there were rouges out there who I angered by doing it. It may not have been the intent of this.x, but for totally superficial reasons, has become the de facto way of knowing you’re calling a member property/field/method, and not having to bother with memorizing some style guide’s idea of how you should represent these things.
Also, just for speed of development, say I want to call a method but I don’t know the exact name, typing “this.” gives me an intellisense list of everything available in a compact, scrollable list. Makes my life a lot easier.
I'd argue that this.myValue = myValue is a lot clearer than the 'conventional' MyValue = myValue, unless you live in a world where your linter can mandate pascalcase for private fields always (and never otherwise).
It's too hard to rely on convention to communicate details across an org, especially when using 'this' is what your devs default to (perhaps a relic from their Java days in school).
It basically guarantees that whenever I see a symbol, I know where it's coming from.
If I see:
`myFoo`
Cool, it must have been declared somewhere in this scope of code.
If I see:
`this.myFoo`
Cool, it's declared as a field on the class and therefore exposed at a higher level (even if it's private, changing its value can have side effects later on outside this scope since it is persisted state on my class).
Note that this only really works when your linter guarantees it. But as a developer, I will always take a guarantee over a non-guarantee :)
I've never liked added explicitness for readability in tool heavy environments (which C#/VS is) since it tends to not add much value because those tools can impart the same information. If we were doing C# in a really basic text editor, I could understand the need for qualifying 'this' though.
Visual Studio (without third-party extensions) still doesn't offer a way to color/highlight/style static member call-sites differently to instance member call-sites, that's why I always prefix instance member access with `this.` and why I always give static fields a name with a leading underscore.
Ah, yes - that's a new setting in VS2019 (I use VS2017 as my daily driver, but sometimes use VS2019).
It looks like VS2019 will only let you style static members in bold - or not - and that's it. You can't use a different color or italics - just bold or non-bold. Hmpf.
I like explicitness for readability because I hate tool heavy environments! Most Java/C# IDEs are quite resources hungry, and noticeably slow down my Macbook.
That's a fair argument. However I'd counter by saying that code is often read in "tool light" environments, such as a diff in an email, code in an online repository, etc.
IDEs can highlight local fields and class members in different colors. Furthermore, in C# convention, member variables are preceded with an underscore (e.g. `_myFoo`).
>I've had coworkers who would put this before every method call, because...? When calling your own method, in your own class, that inherits/implements no other classes, why on earth would you decorate your own method call with this?
Because it's consistent with the pattern of [object].[method](). When you call a method in class B from class A, the call is b.someMethod(). When you call a method in class A from another method in class A, the call is this.someMethod().
I personally find that the consistency makes the code easier to parse and read. If I join an existing project where "this" isn't being used already, I wouldn't push it. As long as your consistent either way it's not a big deal, but for new projects where I get a say in it, it is my preference.
Yeah, I don't usually include "this" when calling methods on the same object, but it's not like it enrages me or anything. I totally get why you would, and it's fine.
I generally agree with "consistency is good", but for an issue like this: honestly, who cares? This is SUCH a small difference that even if you're inconsistent, I doubt I'd even notice it or pay it a second thought. If you're going to work with other human beings, you can't be this insanely dogmatic, you'll never get anything done.
I really like Golang's choice to not offer inheritance, but instead an alternative: embedding. Which is really just composition, but where 1. the child is named implicitly after its type, and 2. its methods and members are automatically promoted to visibility in the "namespace" of the parent (but still "live in" the child.)
So, if you've got Go code like this:
type B struct {
int c
}
type A struct {
B
}
...then if you type `anA.c`, it's basically the same as if you had written `anA.B.c`. It's just sugar.
And, as with inheritance, members+methods defined explicitly on the parent (A) shadow the ones from the child (B), when you're accessing them on the parent. So you can do something that looks a lot like "subclass method overriding" on the child. (Though it isn't, quite, because the embedded child's methods, once reached, will only call each-other, oblivious to the parent. In C++ terms, there are no "virtual" methods.)
This is more often used for decoration or aggregation (e.g. Go's bufio.ReadWriter, which is just a struct embedding a bufio.Reader and a bufio.Writer), but it can be used to simulate inheritance pretty well, with almost none of the disadvantages that come from having inheritance built into your type system.
(For example, there's no need for the Liskov Substitution Principle in Golang, since you can't pass an embedding "subclass" (A) instance into a method parameter that wants the "base class" type (B). If you want that behavior, you opt into it explicitly by defining the method parameter as being of an interface type, where the interface is one that B implements; then, anything that embeds B will—unless it shadowed B's methods with methods of different signatures—also meet that interface.)
What on earth does this have to do with the topic at hand? There are plenty of places where composition/inheritance have been discussed and will be discussed. It doesn't need to be brought up every single time someone mentions a language that supports OOP.
> I personally find that the consistency makes the code easier to parse and read.
> As long as your consistent
knowing when to break consistency is a sign of education and superiority. The point of it is to be difficult, to make those who know identifiable and part of a club, whether the club is grammar nazis or, well, grammar nazis.
If only we could make a push to regularize and consistentize more things, without it being called "dumbing down" or "satire".
-4 votes. HN must really hate suggesting that minor distinctions that do nothing to help and are only kept in the world to prove you know them, are a waste. Or didn't read my comment.
You know what HN hates more than "suggesting that minor distinctions that do nothing to help and are only kept in the world to prove you know them, are a waste?" Complaining about downvotes.
Yes, there is a reason the saying "a foolish consistency is the hobgoblin of little minds" is a thing. (Incidentally, it's a quote from Ralph Waldo Emerson.) But, my experience, and that of many others is that having a consistently styled codebase makes things a lot easier when making changes later.
Yes, there are tradeoffs, but, in engineering, we learn to figure out which tradeoffs are worth making. That's the point people are trying to make, and it is not a trivial one.
Edit: also note the word "foolish" in this context. "Foolish consistency" would be taking the consistency principle to levels where it no longer provides benefits.
So we're agreed that consistency is a good thing, and that making things easier is good?
Why are you saying it in the style of disagreeing?
> Complaining about downvotes.
I'm not complaining about downvotes, I'm accusing people of not reading. I think people saw my comment as pointing out the wrong "your" and reflexively downvoted it. I'm prompting people to see that's not the case.
Well, accusing people of not reading is going to net you downvotes. Tone does matter if you're concerned about fake internet points.
Yes, consistency is good. Making things easier is good. Are you actually arguing for using "this" when it's syntactically unnecessary, or against? It isn't clear from what you wrote whether you're even taking a position either way (although, I do agree that you should pick one and be consistent about it -- I favor using "this", even when it's not necessary).
> Are you actually arguing for using "this" when it's syntactically unnecessary, or against?
I'm arguing that C# should have made it mandatory or never required, so "sometimes unnecessary" is no longer a thing, so having to learn when it is and isn't necessary isn't a thing, and "I know when it's unnecessary and that makes me better than other developers" blog posts aren't a thing, and "I use it even when it's unnecessary because {other good reasons}" retorts aren't a thing, and that if we pushed for that kind of consistency universally, instead of admiring the cleverness of shaving 5 characters off a mountain of verbose C# or admiring the people who know when you can and can't do so, many things would be simpler, and that would be better.
For example, merging "your" and "you're" one way or the other, because everyone knows what they mean from context and they sound the same anyway, or removing "you're" in favour of "you are".
Well, then you should have literally written this instead of your first comment. Here, you've actually said something, and it doesn't come off as unjustified criticism of specific people whom you quoted. And, I now recognize that you have a point, which means you've successfully communicated.
I suspect that if you go back and read my comments, you'll see me saying that it would be nice if things were more consistent, simpler, and that "minor distinctions that do nothing to help are a waste".
> Well, then you should have literally written this instead
Somewhere between victim blaming and invoking the Just World hypothesis. You introduced the idea that I should care about downvotes, you blamed my downvotes on complaining about them. Then when I denied that, you blamed the downvotes on me being accusatory. Now you've settled on the downvotes being because I'm not good enough at communication, and now you have a reason why I deserve them, you can tell me how I "should literally" have behaved if I didn't want them - a suggestion only you have pushed. That's annoyingly smug with 20/20 useless hindsight. Yes maybe it would have been good from a downvote point of view if I had literally written something that took me hours to get round to framing, instead, but I didn't, and can't, and if the cost of that is downvotes then so be it.
How did the article not mention extension methods, when that's arguably the only true use case (many are against such methods).
I'm a big C# fan, I like a lot about the language, but the inheritance is especially cumbersome and it can become a minefield for the uninitiated. It's only something you avoid when you have tripped by it. The biggest minefield is when using them in initializers, but I'm pretty sure the compilar has displayed warning for sometime and I believe Resharper has had it forever (.net 3.5?).
The only legitimate uses of 'this' is when is when using indexers and when using 'this' as the first parameter in extension methods. Nothing else springs to mind, and as mentioned above, 'base' should normally be used in indexors.
However, there are times when I have used it for readability (which could be considered as an antipattern). I guess this is an example of why languages become so complex. Semantic sugar everywhere (it's addictive!)
Everything besides what remains after you run a minifier is superfluous. (Which is more of a JS thing, but bear with me.) Lots of reasons we don’t write code that looks like that.
I adopted this style after working in TypeScript for a while and then going back to C#. I came to really like having an explicit receiver on every function. I work in a lot of languages where that's required, such as TS and Rust, and now the “normal” C# style of calling a method without receiver is confusing.
Also lots of people love to add _ or m_ before fields to distinguish them from local variables, so why not just use `this.`? I think once you actually use this style it starts to make a lot more sense.
I personally think reasons like this are just pulled out of thin air to justify simple style preferences. For example, `this` is an entire word that the editor draws in a different color, so it seems unlikely that `_` is easier to scan for. Even I'm not claiming to have objective reasons for preferring `this`.
Color me odd, I did do 20+ years of Smalltalk, that weird "objects all the way down" language where self was not an option.
What I have observed anecdotally over the the last 10 years as I've become much more of a polyglot is that, very generalisticaly speaking, spheres that frown on self/this produce code that is less "objecty" than otherwise. Spheres that eschew it's use often feel like just simpler C. And to be honest, that's fine. If you thing object oriented programming is just about "better organizing/structuring" your code, then do the ALGOL style thing. But if you want to have that "my God, it's full of objects" experience, try being explicit with your message sends.
I do a middle ground: I use "this" for a method call specifically when the call is occurring within the context of an instantiation of a class. As opposed to a static method calling a static method, where the method name goes unprefixed, because there is no object that would be represented by "this" (and C# doesn't even allow it.)
Curious how you would think of this approach. Would you call that inconsistent, or a useful separation of thought patterns?
In C#, 'this' is how you gain access to extension methods for the current class. At least, that's how you get most tooling to expose them as viable completion candidates.
Calling a method on base besides the method you are overriding is a rather malodorous code smell. It's saying "I want to invoke a method on this instance, but with behavior that differs from how it's defined for this instance".
In the post I mentioned that the manager wanted developer to use "this." to signify that they were using the base class's method.
Which isn't correct. Lets say someone were to come in and override the base class's method, now calling this.SomeMethod() would not be the intended behavior of the original code that was improperly using "this." as "base."
I don't want "base." or "this." in my code at all unless there is some incredibly rare case that I MUST use it.
While I have seen this behaviors, they are not the norm at all (>100 devs). C# style is avoiding this keyword and tools (resharper etc) are even highlight unnecessary use.
>, but the closest I will get to accepting it is in a constructor where you are passing values that will be stored as private fields. int maxAmount; SomeClass(int maxAmount) => this.maxAmount = maxAmount;
>But even in this case, you should really be using Pascal casing as per Microsoft's Capitalization Conventions.
Like other sibling comments stated, I also disagree. The C# compiler knows about "this" but not about arbitrary Pascal naming conventions. Therefore, it's more reliable to choose the syntax where keyboard typos can be detected by the compiler.
The blog author's advice would make more sense if C# compiler assigned semantic meaning to alpha case like Golang. In Golang, the first letter of identifiers being upper vs lowercase changes the scope of visibility: https://golang.org/doc/effective_go.html#names
Also an excerpt from Microsoft guidelines cited in sibling comment that recommends using "this." :
>Do not use a prefix for member variables (_, m_, s_, etc.). If you want to distinguish between local and member variables you should use “this.” in C# and “Me.” in VB.NET.
In Python, the only way to access members of the current object is by explicitly using self (which should really have been called this in line with other languages, but that's another matter). [0]
This means there's never any confusion at all as to what is a member and what is a local.
In C#, this confusion is possible, if you name your private members the same way as your locals. Microsoft recommends and uses a convention which does exactly this. [1][2]
edit The point being that this.myThing will cause a compilation error unless myThing really is a member, giving an ironclad guarantee to the reader that it is indeed a member. Unlike in Python, in C# it's not possible to give the reader an ironclad guarantee that a local really is a local, as the implicit this cannot be disabled.
> In C#, this confusion is possible, if you name your private members the same way as your locals.
This is also an issue with own methods versus static imports.
> Microsoft recommends and uses a convention which does exactly this. [1][2]
The article mentions this:
> I know, capitalization conventions change over time, and I could have sworn there was a time when camel casing was the recommended approach for fields (specifically private fields)
Only parameters remain conventionally camelCased, and it makes sense that they remain specified as C# allows for named parameters (so parameter names are part of the public interface).
Your link explicitly states that it does not cover private fields:
> Internal and private fields are not covered by guidelines
Which is specifically what I noted was dropped from the document linked by TFA.
> Pascal case, same as Properties so they can be seamlessly refactored.
Your link also explicitly states that it only applies to static public or protected fields, and that public instance fields are forbidden by the member design guidelines*:
> The field-naming guidelines apply to static public and protected fields […] public or protected instance fields are not allowed by the member design guidelines.
So the only "seamless refactoring" which is allowed is essentially irrelevant (it's switching between static fields and static properties).
I hadn't wanted to get into the weeds of Python, but yes. You could use any identifier you want, but breaking with convention in this way is not a wise move.
I consider it a mistake on the part of Python to go with self rather than this, but it's a really bad idea to write code that surprises other programmers in that way.
> Use $this to refer to the current object. Use self to refer to the current class. In other words, use $this->member for non-static members, use self::$member for static members.
This is a different way of doing things, yes, but it makes sense.
Whenever I read articles like this, I happily reflect that C# is such an excellent language to work with that these tiny complaints (I would hesitate to call them "issues") are the only ones popping up.
One other advantage to the "this.Foo()" syntax is that this allows using the extension method "Foo", which otherwise could not be resolved by the compiler.
(I also briefly considered if extension methods invoked on "this" would bind more strongly than base types - however, that is never the case [0])
I have a similar perspective. For me, the first reaction after getting halfway through the article was "this is a pedantic distraction".
I don't worry too much about these things. The whole point of something high level like C# is to be able to focus more on the problem domain than the language features. In most cases, I would just let VS clean these things up for me. I very rarely disagree with what the latest version of VS2019 suggests for code cleanup tasks.
> One other advantage to the "this.Foo()" syntax is that this allows using the extension method "Foo", which otherwise could not be resolved by the compiler.
I’d argue that calling an extension method of the class from within the class is a good indicator that said extension method should be added as a member... it’s not really an “extension” if it’s required for the class to compile.
IIRC (and, it has been a long time so please be gentle with the down arrow if I'm wrong, lol), you can write extension methods in native code that you might want to call from within the class.
The language is good; the standard library drives me batty. So many things that simply do not work as stated, or that force you take very circuitous routes to arrive at very simple results.
I recall having particular trouble with strings, filesystems (especially watchers; though that may be a domain issue more than a lib issue); and in more recent impressions, the TPL (task parallel library) was nightmarish, its behaviour never adding up to what was documented.
That, or change the IDE style preference that triggers this suggestion to suit your preferred style, preferably using a mechanism like .editorconfig that embeds these preferences within the project itself.
There's nothing sacred about Visual Studio defaults; give me an IDE and a language I use regularly, and there's probably at least one default style preference I disagree with (and typically more, especially for C-like languages where the currently fashionable defaults place a newline before every keyword and brace).
As for this, I'd actually prefer a Python-like convention making the instance explicit in instance method parameter lists and bodies, but, given that implicit this exists in the first place, I don't really have a preference, and therefore stick with the conventional default — omit unnecessary this — unless working on an existing project whose established style includes it.
> give me an IDE and a language I use regularly, and there's probably at least one default style preference I disagree with
But that is disingenuous. We aren't talking about [insert opensource language] + [insert opensource IDE], where your the IDE's inbuilt preferences match closer to the IDE developer's preference than the random language you are developin in it.
This is Microsoft's Visual Studio and Microsoft's C#. Their linter is recommending the best practice conventions.
You can definitely disagree with them, but I don't, that is why I wrote this piece. I don't like "this." scattered throughout the code when it isn't proper according to the language designers.
Everyone's chiming in with "you should always use 'this' because it's more explicit", which I personally tend to agree with. But there is a dimension to this that may not be obvious to people who don't come from Java/C#: these languages don't have non-member functions or variables. So if you're accessing a variable without [obj]. it's either a member of the current object, or it's a local variable in the current function. If you call a function without [obj]. it's unlikely (maybe impossible? I'm not certain) that it isn't a method of the current object. On top of that, by idiom Java and C# code tends to be dramatically more verbose than many other languages. So I could understand the desire to cut that down some when there would also be less ambiguity than in, say, JavaScript.
Edit: @masklinn pointed out the static imports feature, which allows you to import static methods in a such a way that they don't have to be prefixed with the class name when calling them, so I take back what I said about function calls
> these languages don't have non-member functions or variables
Not true. Both have static imports. Which means in e.g.
PI * Pow(Radius, 2);
all three symbols may or may not be part of the current class. In this case, only Radius is, the other two come from `using static System.Math` (it's straight from an official example for the `using static` directive).
Also
> it's either a member of the current object, or it's a local variable in the current function.
So they do have non-member variables, in local variables. Making it clear that something is not a local variable is valuable as it means the variable has a much larger scope than you might expect.
I didn't know about static imports. Technically those are still member functions, but you are able to call them without a prefix, so I retract that point.
> So they do have non-member variables, in local variables. Making it clear that something is not a local variable is valuable as it means the variable has a much larger scope than you might expect.
Yes, local variables are non-member variables. I'm just pointing out that people's habits may have been built in JavaScript or the like, where a non-member variable could be:
- a global
- from a closure, anywhere up the tree
- an import from another file
Whether or not the explicitness is still important in C# code, it's at least much more important in JavaScript and Python code (in fact I'm pretty sure both languages require it)
> Yes, local variables are non-member variables. I'm just pointing out that people's habits may have been built in JavaScript or the like, where a non-member variable could be:
> - a global
> - from a closure, anywhere up the tree
> - an import from another file
C# has "from a closure, anywhere up the tree" and "an import from an other file" though, the only thing it arguably doesn't have is "a global".
> Whether or not the explicitness is still important in C# code, it's at least much more important in JavaScript and Python code (in fact I'm pretty sure both languages require it)
Technically you can use the `with` statement to make it implicit in javascript.
How common is it for code editing tools to be able to highlight local methods v statically imported ones differently? I know Eclipse does it, but I don't know how prevalent the feature is. e.g. Can Vim do it?
Not sure if Vim can do it, but code can be read outside of editors. Sometimes people review PRs in browsers. I can see why there might be a confusion when using static imports or properties/methods from the base class without the base keyword.
That is perfectly fine, but in this case, the manager wanted this to explicitly signify base, If you didn't provide this, it meant it was a MyClass method.
And I agree it is dangerous - going against conventions on giant projects with dozens of developers, is dangerous. Should have left off the base. and the this. everywhere, like Visual Studio recommends.
It is about tastes I've had most of my C# developing life. Taste's that coincidentally align with the conventions of Microsoft Visual Studio's built in linter.
I discourage the use of "this" except for field references, in C#.
Field access and modification are the most important part of a member to consider. Mutation is a well-recognized pattern for bugs. I want the points in the method at which mutation occurs to be highlighted. The use of "this" to distinguish fields from locals makes that possible.
If you've been programming for a few years, frequently just the field access pattern gives you an intuition of what sort of member you're looking at in just a glance.
The programmer's brain holds limited context at any time. The larger the context required, the less detailed the understanding. Being able to predict what a method does in a glance means the developer better preserves their current context.
I strongly avoid inheritance, so I rarely have use of "base". Again, when I'm explicitly invoking "base", I really want that to stand out, because it's unusual.
(For this same reason, I also discourage explicit use of the "private" access modifier. Everything should be private, except for the few things that must be public. Extra access modifiers add noise, which distracts from the important information.)
Finally, I strive to make my code read as fluently as possible. In my experience, fluent code makes it harder for bugs to hide. The ability to clearly express a concept in a spoken language correlates very highly with the ability to implement that concept in a program without errors.
Compare:
if (AllChildOperationsAreComplete) { StartNextOperation(); }
if (this.AllChildOperationsAreComplete) { this.StartNextOperation(); }
The extra hiccoughs in the expression of the second form are each interruptions, each interruption increasing the chance that you drop some context while reading the code.
Last time I worked in a C# code base I made the entire code base StyleCop-clean. StyleCop has a rule that you are supposed to use an explict "this", although it may only be for field access (I can't remember).
Personally I think having a consistent style is more important than the details of that style, on the balance of things (use your judgment, this ain't a strict rule) and I love that we have tools like StyleCop.
I know lots of programmers who discourage using 'this' when accessing class fields, because it's "not needed", but at the same time use "m_" prefix for fields.
The convention for using m_ prefix is used to signal visually what is a private member and also p_ prefix is for params. I don't like it that much and I've seen it both in Java and .Net but, if I'm working on a code base which uses this convention I;ll simply stick to it. Consistency is nice, inconsistency not so.
Well, this.field also can be used to signal visually what is a private member or what is a private method. And it's supported by the language, and there's no need to use such magic prefix strings.
My point was that the same people who insist that 'this' is superfluous because "IDE can handle it" are also advocating use of "m_" because of "visual signal". I simply think 'this' is superior to "m_" in every way.
I feel like this is an excellent area for a post-checkout / pre-checkin script to process code to / from the style guide's recommendations and your own personal preference. After all, the machines are here to serve us, not us to serve them.
Lot of personal preferences masquerading as objective truths in this article.
My personal preference for C#: private fields are camelCased and are always prefixed with this on access (disambiguating field from parameter access); methods and properties are not prefixed. I find this gives a nice balance between code noise and explicitness.
Same principle could be applied to method access (since C# has local methods and static imports) and I would happily concede that it is a sane approach - but I don't find the code noise it produces is worth it.
If I join an existing project that consistently uses some other approach (even if it's an old-school underscore-prefixed fields approach) that's OK too.
Yeah I don't use Fully qualified class names nor this unless I have to. If I have any question about the scope a quick hover tells me everything I need to know.
I also skip brackets with single line if statements and many other optional explicit things you could do but add unneeded text to the code, seems strange to not use language features to make the code more terse.
If its not good practice I wish they would just take the feature out of the language and make everyone run a linter before upgrading to the new more explicit language version for conversion.
135 comments
[ 1.9 ms ] story [ 124 ms ] threadI do this all the time, and I didn’t know there were rouges out there who I angered by doing it. It may not have been the intent of this.x, but for totally superficial reasons, has become the de facto way of knowing you’re calling a member property/field/method, and not having to bother with memorizing some style guide’s idea of how you should represent these things.
Also, just for speed of development, say I want to call a method but I don’t know the exact name, typing “this.” gives me an intellisense list of everything available in a compact, scrollable list. Makes my life a lot easier.
It's too hard to rely on convention to communicate details across an org, especially when using 'this' is what your devs default to (perhaps a relic from their Java days in school).
It basically guarantees that whenever I see a symbol, I know where it's coming from.
If I see: `myFoo`
Cool, it must have been declared somewhere in this scope of code.
If I see: `this.myFoo`
Cool, it's declared as a field on the class and therefore exposed at a higher level (even if it's private, changing its value can have side effects later on outside this scope since it is persisted state on my class).
Note that this only really works when your linter guarantees it. But as a developer, I will always take a guarantee over a non-guarantee :)
I can't find when it started happening, but there is at least someone wanting to turn it off Jan 2019: https://developercommunity.visualstudio.com/idea/437785/allo...
It looks like VS2019 will only let you style static members in bold - or not - and that's it. You can't use a different color or italics - just bold or non-bold. Hmpf.
> Cool, it's declared as a field on the class
IDEs can highlight local fields and class members in different colors. Furthermore, in C# convention, member variables are preceded with an underscore (e.g. `_myFoo`).
Because it's consistent with the pattern of [object].[method](). When you call a method in class B from class A, the call is b.someMethod(). When you call a method in class A from another method in class A, the call is this.someMethod().
I personally find that the consistency makes the code easier to parse and read. If I join an existing project where "this" isn't being used already, I wouldn't push it. As long as your consistent either way it's not a big deal, but for new projects where I get a say in it, it is my preference.
I generally agree with "consistency is good", but for an issue like this: honestly, who cares? This is SUCH a small difference that even if you're inconsistent, I doubt I'd even notice it or pay it a second thought. If you're going to work with other human beings, you can't be this insanely dogmatic, you'll never get anything done.
So, if you've got Go code like this:
...then if you type `anA.c`, it's basically the same as if you had written `anA.B.c`. It's just sugar.And, as with inheritance, members+methods defined explicitly on the parent (A) shadow the ones from the child (B), when you're accessing them on the parent. So you can do something that looks a lot like "subclass method overriding" on the child. (Though it isn't, quite, because the embedded child's methods, once reached, will only call each-other, oblivious to the parent. In C++ terms, there are no "virtual" methods.)
This is more often used for decoration or aggregation (e.g. Go's bufio.ReadWriter, which is just a struct embedding a bufio.Reader and a bufio.Writer), but it can be used to simulate inheritance pretty well, with almost none of the disadvantages that come from having inheritance built into your type system.
(For example, there's no need for the Liskov Substitution Principle in Golang, since you can't pass an embedding "subclass" (A) instance into a method parameter that wants the "base class" type (B). If you want that behavior, you opt into it explicitly by defining the method parameter as being of an interface type, where the interface is one that B implements; then, anything that embeds B will—unless it shadowed B's methods with methods of different signatures—also meet that interface.)
> decorate your own method
> I personally find that the consistency makes the code easier to parse and read.
> As long as your consistent
knowing when to break consistency is a sign of education and superiority. The point of it is to be difficult, to make those who know identifiable and part of a club, whether the club is grammar nazis or, well, grammar nazis.
If only we could make a push to regularize and consistentize more things, without it being called "dumbing down" or "satire".
Yes, there is a reason the saying "a foolish consistency is the hobgoblin of little minds" is a thing. (Incidentally, it's a quote from Ralph Waldo Emerson.) But, my experience, and that of many others is that having a consistently styled codebase makes things a lot easier when making changes later.
Yes, there are tradeoffs, but, in engineering, we learn to figure out which tradeoffs are worth making. That's the point people are trying to make, and it is not a trivial one.
Edit: also note the word "foolish" in this context. "Foolish consistency" would be taking the consistency principle to levels where it no longer provides benefits.
Why are you saying it in the style of disagreeing?
> Complaining about downvotes.
I'm not complaining about downvotes, I'm accusing people of not reading. I think people saw my comment as pointing out the wrong "your" and reflexively downvoted it. I'm prompting people to see that's not the case.
Yes, consistency is good. Making things easier is good. Are you actually arguing for using "this" when it's syntactically unnecessary, or against? It isn't clear from what you wrote whether you're even taking a position either way (although, I do agree that you should pick one and be consistent about it -- I favor using "this", even when it's not necessary).
I'm arguing that C# should have made it mandatory or never required, so "sometimes unnecessary" is no longer a thing, so having to learn when it is and isn't necessary isn't a thing, and "I know when it's unnecessary and that makes me better than other developers" blog posts aren't a thing, and "I use it even when it's unnecessary because {other good reasons}" retorts aren't a thing, and that if we pushed for that kind of consistency universally, instead of admiring the cleverness of shaving 5 characters off a mountain of verbose C# or admiring the people who know when you can and can't do so, many things would be simpler, and that would be better.
For example, merging "your" and "you're" one way or the other, because everyone knows what they mean from context and they sound the same anyway, or removing "you're" in favour of "you are".
I suspect that if you go back and read my comments, you'll see me saying that it would be nice if things were more consistent, simpler, and that "minor distinctions that do nothing to help are a waste".
> Well, then you should have literally written this instead
Somewhere between victim blaming and invoking the Just World hypothesis. You introduced the idea that I should care about downvotes, you blamed my downvotes on complaining about them. Then when I denied that, you blamed the downvotes on me being accusatory. Now you've settled on the downvotes being because I'm not good enough at communication, and now you have a reason why I deserve them, you can tell me how I "should literally" have behaved if I didn't want them - a suggestion only you have pushed. That's annoyingly smug with 20/20 useless hindsight. Yes maybe it would have been good from a downvote point of view if I had literally written something that took me hours to get round to framing, instead, but I didn't, and can't, and if the cost of that is downvotes then so be it.
I'm a big C# fan, I like a lot about the language, but the inheritance is especially cumbersome and it can become a minefield for the uninitiated. It's only something you avoid when you have tripped by it. The biggest minefield is when using them in initializers, but I'm pretty sure the compilar has displayed warning for sometime and I believe Resharper has had it forever (.net 3.5?).
The only legitimate uses of 'this' is when is when using indexers and when using 'this' as the first parameter in extension methods. Nothing else springs to mind, and as mentioned above, 'base' should normally be used in indexors.
However, there are times when I have used it for readability (which could be considered as an antipattern). I guess this is an example of why languages become so complex. Semantic sugar everywhere (it's addictive!)
Extention Methods https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
Also lots of people love to add _ or m_ before fields to distinguish them from local variables, so why not just use `this.`? I think once you actually use this style it starts to make a lot more sense.
Color me odd, I did do 20+ years of Smalltalk, that weird "objects all the way down" language where self was not an option.
What I have observed anecdotally over the the last 10 years as I've become much more of a polyglot is that, very generalisticaly speaking, spheres that frown on self/this produce code that is less "objecty" than otherwise. Spheres that eschew it's use often feel like just simpler C. And to be honest, that's fine. If you thing object oriented programming is just about "better organizing/structuring" your code, then do the ALGOL style thing. But if you want to have that "my God, it's full of objects" experience, try being explicit with your message sends.
Curious how you would think of this approach. Would you call that inconsistent, or a useful separation of thought patterns?
> I've had managers want developers to use this to signify calling a base class's method, which is incorrect. You should be using base.
I advocate using base for base.
I advocate against using this, as does Visual Studio 2017 and above [1].
1: https://i.imgur.com/9F6Lyx8.png
Which isn't correct. Lets say someone were to come in and override the base class's method, now calling this.SomeMethod() would not be the intended behavior of the original code that was improperly using "this." as "base."
I don't want "base." or "this." in my code at all unless there is some incredibly rare case that I MUST use it.
I understand his suffering :)
>But even in this case, you should really be using Pascal casing as per Microsoft's Capitalization Conventions.
Like other sibling comments stated, I also disagree. The C# compiler knows about "this" but not about arbitrary Pascal naming conventions. Therefore, it's more reliable to choose the syntax where keyboard typos can be detected by the compiler.
The blog author's advice would make more sense if C# compiler assigned semantic meaning to alpha case like Golang. In Golang, the first letter of identifiers being upper vs lowercase changes the scope of visibility: https://golang.org/doc/effective_go.html#names
Also an excerpt from Microsoft guidelines cited in sibling comment that recommends using "this." :
>Do not use a prefix for member variables (_, m_, s_, etc.). If you want to distinguish between local and member variables you should use “this.” in C# and “Me.” in VB.NET.
This means there's never any confusion at all as to what is a member and what is a local.
In C#, this confusion is possible, if you name your private members the same way as your locals. Microsoft recommends and uses a convention which does exactly this. [1][2]
edit The point being that this.myThing will cause a compilation error unless myThing really is a member, giving an ironclad guarantee to the reader that it is indeed a member. Unlike in Python, in C# it's not possible to give the reader an ironclad guarantee that a local really is a local, as the implicit this cannot be disabled.
[0] https://stackoverflow.com/a/1984121/
[1] https://web.archive.org/web/20100316191542/http://blogs.msdn...
[2] https://github.com/microsoftgraph/msgraph-sdk-dotnet-core/bl...
This is also an issue with own methods versus static imports.
> Microsoft recommends and uses a convention which does exactly this. [1][2]
The article mentions this:
> I know, capitalization conventions change over time, and I could have sworn there was a time when camel casing was the recommended approach for fields (specifically private fields)
It looks like "private fields" (along with private everything) have been completely dropped from the conventions: https://docs.microsoft.com/en-us/dotnet/standard/design-guid...
Only parameters remain conventionally camelCased, and it makes sense that they remain specified as C# allows for named parameters (so parameter names are part of the public interface).
Pascal case, same as Properties so they can be seamlessly refactored.
Your link explicitly states that it does not cover private fields:
> Internal and private fields are not covered by guidelines
Which is specifically what I noted was dropped from the document linked by TFA.
> Pascal case, same as Properties so they can be seamlessly refactored.
Your link also explicitly states that it only applies to static public or protected fields, and that public instance fields are forbidden by the member design guidelines*:
> The field-naming guidelines apply to static public and protected fields […] public or protected instance fields are not allowed by the member design guidelines.
So the only "seamless refactoring" which is allowed is essentially irrelevant (it's switching between static fields and static properties).
I consider it a mistake on the part of Python to go with self rather than this, but it's a really bad idea to write code that surprises other programmers in that way.
self makes more sense though. And smalltalk used self. And so did (obviously) Self.
The most important part is to not use both (which of course is what PHP does).
> Use $this to refer to the current object. Use self to refer to the current class. In other words, use $this->member for non-static members, use self::$member for static members.
This is a different way of doing things, yes, but it makes sense.
There doesn't seem to be an easy way to detect it using external tooling, either: https://stackoverflow.com/q/957766/
I've posted a new answer there on how to configure the check in VS2019.
One other advantage to the "this.Foo()" syntax is that this allows using the extension method "Foo", which otherwise could not be resolved by the compiler.
(I also briefly considered if extension methods invoked on "this" would bind more strongly than base types - however, that is never the case [0])
[0] https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
I don't worry too much about these things. The whole point of something high level like C# is to be able to focus more on the problem domain than the language features. In most cases, I would just let VS clean these things up for me. I very rarely disagree with what the latest version of VS2019 suggests for code cleanup tasks.
I’d argue that calling an extension method of the class from within the class is a good indicator that said extension method should be added as a member... it’s not really an “extension” if it’s required for the class to compile.
But it’s nothing I’d lose sleep over...
https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUHqAQwFs...
Developers would be wise not to mistake reified opinions with correctness.
1: https://imgur.com/a/UTGrYsq
There's nothing sacred about Visual Studio defaults; give me an IDE and a language I use regularly, and there's probably at least one default style preference I disagree with (and typically more, especially for C-like languages where the currently fashionable defaults place a newline before every keyword and brace).
As for this, I'd actually prefer a Python-like convention making the instance explicit in instance method parameter lists and bodies, but, given that implicit this exists in the first place, I don't really have a preference, and therefore stick with the conventional default — omit unnecessary this — unless working on an existing project whose established style includes it.
But that is disingenuous. We aren't talking about [insert opensource language] + [insert opensource IDE], where your the IDE's inbuilt preferences match closer to the IDE developer's preference than the random language you are developin in it.
This is Microsoft's Visual Studio and Microsoft's C#. Their linter is recommending the best practice conventions.
You can definitely disagree with them, but I don't, that is why I wrote this piece. I don't like "this." scattered throughout the code when it isn't proper according to the language designers.
Edit: @masklinn pointed out the static imports feature, which allows you to import static methods in a such a way that they don't have to be prefixed with the class name when calling them, so I take back what I said about function calls
Not true. Both have static imports. Which means in e.g.
all three symbols may or may not be part of the current class. In this case, only Radius is, the other two come from `using static System.Math` (it's straight from an official example for the `using static` directive).Also
> it's either a member of the current object, or it's a local variable in the current function.
So they do have non-member variables, in local variables. Making it clear that something is not a local variable is valuable as it means the variable has a much larger scope than you might expect.
> So they do have non-member variables, in local variables. Making it clear that something is not a local variable is valuable as it means the variable has a much larger scope than you might expect.
Yes, local variables are non-member variables. I'm just pointing out that people's habits may have been built in JavaScript or the like, where a non-member variable could be:
- a global
- from a closure, anywhere up the tree
- an import from another file
Whether or not the explicitness is still important in C# code, it's at least much more important in JavaScript and Python code (in fact I'm pretty sure both languages require it)
> - a global
> - from a closure, anywhere up the tree
> - an import from another file
C# has "from a closure, anywhere up the tree" and "an import from an other file" though, the only thing it arguably doesn't have is "a global".
> Whether or not the explicitness is still important in C# code, it's at least much more important in JavaScript and Python code (in fact I'm pretty sure both languages require it)
Technically you can use the `with` statement to make it implicit in javascript.
You should not, but you can.
It could also be a field in the parent class. Protected fields are a bad idea but I’m sure some people use them.
Having said that, C# also permits you to have fields with the same name in both the parent class and the current object.
This will give you a compiler warning suggesting you use the new keyword, though.
My rule is exactly the opposite. Only allow `base` in:
- Constructors
- Overrides
And I agree it is dangerous - going against conventions on giant projects with dozens of developers, is dangerous. Should have left off the base. and the this. everywhere, like Visual Studio recommends.
Is it just a matter of taste?
What does being a manager have to do with code style? This is textbook micromanagement.
Field access and modification are the most important part of a member to consider. Mutation is a well-recognized pattern for bugs. I want the points in the method at which mutation occurs to be highlighted. The use of "this" to distinguish fields from locals makes that possible.
If you've been programming for a few years, frequently just the field access pattern gives you an intuition of what sort of member you're looking at in just a glance.
The programmer's brain holds limited context at any time. The larger the context required, the less detailed the understanding. Being able to predict what a method does in a glance means the developer better preserves their current context.
I strongly avoid inheritance, so I rarely have use of "base". Again, when I'm explicitly invoking "base", I really want that to stand out, because it's unusual.
(For this same reason, I also discourage explicit use of the "private" access modifier. Everything should be private, except for the few things that must be public. Extra access modifiers add noise, which distracts from the important information.)
Finally, I strive to make my code read as fluently as possible. In my experience, fluent code makes it harder for bugs to hide. The ability to clearly express a concept in a spoken language correlates very highly with the ability to implement that concept in a program without errors.
Compare:
if (AllChildOperationsAreComplete) { StartNextOperation(); }
if (this.AllChildOperationsAreComplete) { this.StartNextOperation(); }
The extra hiccoughs in the expression of the second form are each interruptions, each interruption increasing the chance that you drop some context while reading the code.
1: https://i.imgur.com/9F6Lyx8.png
Personally I think having a consistent style is more important than the details of that style, on the balance of things (use your judgment, this ain't a strict rule) and I love that we have tools like StyleCop.
My point was that the same people who insist that 'this' is superfluous because "IDE can handle it" are also advocating use of "m_" because of "visual signal". I simply think 'this' is superior to "m_" in every way.
My personal preference for C#: private fields are camelCased and are always prefixed with this on access (disambiguating field from parameter access); methods and properties are not prefixed. I find this gives a nice balance between code noise and explicitness.
Same principle could be applied to method access (since C# has local methods and static imports) and I would happily concede that it is a sane approach - but I don't find the code noise it produces is worth it.
If I join an existing project that consistently uses some other approach (even if it's an old-school underscore-prefixed fields approach) that's OK too.
I also skip brackets with single line if statements and many other optional explicit things you could do but add unneeded text to the code, seems strange to not use language features to make the code more terse.
If its not good practice I wish they would just take the feature out of the language and make everyone run a linter before upgrading to the new more explicit language version for conversion.
Then set it as a global rule in .editorconfig (or whatever equivalent tool you’re using) and never think about it again