Using 'this' incorrectly in C#

(jeremyaboyd.com)

49 points | by jermaustin1 1344 days ago

36 comments

  • nend 1344 days ago
    >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.

    • bfrydl 1344 days ago
      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.

      • throwaheyy 1344 days ago
        It's a lot easier to visually scan for _ than for 'this.', quicker to read code that uses _, and it's about 5 times quicker to type.
        • bfrydl 1344 days ago
          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`.
    • OskarS 1344 days ago
      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.

    • travisgriggs 1344 days ago
      This. So this. So very 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.

    • T-hawk 1344 days ago
      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?

    • stefanandcode 1343 days ago
      I also like seeing if a method is static or not at a glance.
    • throw1234651234 1344 days ago
      It's superfluous.
      • masklinn 1344 days ago
        That it's technically superfluous doesn't mean it's practically useless.
        • velox_io 1344 days ago
          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!)

          Extention Methods https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...

      • draw_down 1344 days ago
        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.
      • rcoveson 1344 days ago
        soiswhitespaceinmanylanguages
    • asdfman123 1344 days ago
      I'm just here to say I'd much rather see composition used over inheritance and I don't see a good case for inheritance in most business applications.
      • 0xffff2 1344 days ago
        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.
      • derefr 1344 days ago
        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.)

      • tonyedgecombe 1344 days ago
        If you are using Windows Forms or WPF with C# then you will have to deal with it.
    • jodrellblank 1344 days ago
      > When calling your own method

      > 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".

      • jodrellblank 1344 days ago
        -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.
        • pmiller2 1344 days ago
          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.

          • jodrellblank 1344 days ago
            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.

            • pmiller2 1344 days ago
              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).

              • jodrellblank 1344 days ago
                > 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".

                • pmiller2 1343 days ago
                  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.
                  • jodrellblank 1343 days ago
                    > Here, you've actually said something,

                    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.

  • tantaman 1344 days ago
    I hate all of these rants on questions of style.

    The only problem of style is when there are mixed styles within the same codebase.

    But on that note, every code base should have aggressive linters and auto-formatters that force everyone to use the same style. So the question is moot.

    If you're working in someone else's codebase and their style is different than your preferred style, suck it up because it just doesn't matter.

    --- When moving from a company that didn't have said linters and auto-formatters to one that did, all of these questions disappeared and we could focus solely on solving problems that mattered.

    • pmiller2 1344 days ago
      100% agreed. My company recently did this to our main codebase, and it's been a joy. I can write code now, not play with formatting! I wish it had been this way since day 1.
    • erik_seaberg 1344 days ago
      Style should express intent. Diffs that enforce uniformity without preserving intent are vandalism that poisons “git blame”. Auto-formatting should not be used because it doesn’t understand intent in any way. (And when it does, we will no longer need formatted source files, nor developers.)
    • cjfd 1344 days ago
      I think there actually are bad styles. The google style guide is such a bad style guide. The combination of 2 spaces indent and not putting { and } on top of each other makes it difficult to see at a glance where a block begin and ends.
      • neurotrace 1343 days ago
        I wholeheartedly disagree. Two spaces and the One True Brace style is my preferred way of working. Blocks are easy to identify based on indentation. This is exactly why auto-formatters are the best solution. Then there's no need to have this conversation. Some of the style choices we have at work are not ones I would have chosen but I'm quite comfortable with them now thanks to auto-formatting
    • an_opabinia 1344 days ago
      Many projects vendor code whose styles are not compatible. For C# this is common in Unity3D development. Often external dependencies, vendored, need custom patches, future updates and are not available in VCS. Besides Git is ill-suited for vendoring.

      Next you’ll say “all code should not be vendored.”

      Anyway it’s interesting to disseminate opinions on style because agreement on style beyond the boundaries of a corporate engineering hierarchy is really the best route to solving style issues.

      • acoard 1344 days ago
        Just create a `vendor/` folder and an exclude rule to your linters. Or for Unity include your `Assets/Scripts` folder, whichever fits better.

        >Besides Git is ill-suited for vendoring.

        VCS is ill suited for vendoring, but is there a better option? Vendoring is usually a "hack" in some ways as you're keeping dependancies local when you don't "have to", but if your goal is to keep 'em local then git does a fine job.

        I'm surprised to see push-back for this idea because I've never come across this stumbling block. Please feel free to disagree, as I feel like there might be a perspective I'm not considering or something I can learn.

        • tikhonj 1344 days ago
          This is one of the reasons I like the Nix package manager—I can use Nix to de facto vendor dependencies (at least in the sense of having a local copy where I fully control the version we're on) without the attendant Git/build tool/etc hassle.

          If anything, a Nix derivation with a hash is going to be more reliable than a git commit hash even when you control the repo because it forces the build of your vendored dependency (including any transitive dependencies) to be deterministic. The downside, of course, is that it can be a lot of effort to retrofit deterministic builds on top of external codebases not built with that in mind...

    • cheez 1344 days ago
      I think we should encourage junior developers to be dogmatic about styling because they will want to make positive changes.

      Once you get to a certain level of experience though, it should be a foregone conclusion that all code looks the same automagically.

  • ThePadawan 1344 days ago
    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])

    [0] https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...

    • cgrealy 1344 days ago
      > 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.

      But it’s nothing I’d lose sleep over...

      • wvenable 1344 days ago
        The extension method might be on an interface of the class and not on the class type itself. That's really the only time I've ever had to use this.
      • pmiller2 1344 days ago
        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.
    • bob1029 1344 days ago
      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.

    • Fellshard 1344 days ago
      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.
      • Someone1234 1344 days ago
        Can you provide some examples?
        • Fellshard 1341 days ago
          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.
  • 2bitencryption 1344 days ago
    I like the explicitness of 'this'.

    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 :)

    • vsareto 1344 days ago
      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.
      • lazypenguin 1343 days ago
        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.
      • DaiPlusPlus 1344 days ago
        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.
        • accoil 1344 days ago
          Doesn't Visual Studio make static/const members bold these days?

          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...

          • DaiPlusPlus 1343 days ago
            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.

      • nicoburns 1344 days ago
        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.
    • apta 1343 days ago
      > If I see: `this.myFoo`

      > 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`).

  • MaxBarraclough 1344 days ago
    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.

    [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...

    • masklinn 1344 days ago
      > 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)

      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).

      • jayd16 1344 days ago
        Naming of fields and other members is described here https://docs.microsoft.com/en-us/dotnet/standard/design-guid...

        Pascal case, same as Properties so they can be seamlessly refactored.

        • masklinn 1344 days ago
          > Naming of fields and other members is described here https://docs.microsoft.com/en-us/dotnet/standard/design-guid...

          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).

          • jayd16 1344 days ago
            My comment was meant to be additive and not in conflict with any of your statements.
    • c22 1344 days ago
      You don't have to call it self. You can name the reference whatever you want, this works just as well. Though perhaps it's not as pythonic?
      • MaxBarraclough 1344 days ago
        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.

        • masklinn 1344 days ago
          > I consider it a mistake on the part of Python to go with self rather than this

          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).

          • m_t 1344 days ago
            Yeah but to quote stackoverflow:

            > 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.

      • freedomben 1344 days ago
        I think you are right, but the python guy in me from 10+ years ago has vague memories of people being burned at the stake for such heresy.
    • lostmsu 1344 days ago
      Technically you can disable implicit this: just raise the level of corresponding diagnostic to Error.
    • m4r35n357 1344 days ago
      Yep, my Python code is littered with "self" noise. The PEP "limit" of 80 characters per line on top of that is just taking the piss!
  • jasode 1344 days ago
    >, 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.

  • mwkaufma 1344 days ago
    The author fails to mention the only truly-abusive us of this: working around readonly variables:

      struct Location {
        public readonly float x;
        public readonly float y;
        public Location(float ax, float ay) {
          x = ax;
          y = ay;
        }
        public float X { 
          get { return x; }
          set { this = new Location(value, y); }
        }
      }
    • Someone1234 1344 days ago
      That's evil. I'm both impressed and horrified by that trick.

      I had to try it because I at least thought I might get a compiler/IntelliSense warning, but nope, it works perfectly and silently.

    • jermaustin1 1344 days ago
      I did not mention this because I had no idea this was even possible. Whoever found this out is an psychopath ;).
  • dhruvmittal 1344 days ago
    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).

  • brundolf 1344 days ago
    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

    • masklinn 1344 days ago
      > 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.

      • brundolf 1344 days ago
        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)

        • masklinn 1344 days ago
          > 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.

          You should not, but you can.

      • Bjartr 1344 days ago
        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?
        • kords 1344 days ago
          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.
    • tjalfi 1344 days ago
      > 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.

      It could also be a field in the parent class. Protected fields are a bad idea but I’m sure some people use them.

      • brundolf 1344 days ago
        A field in the parent class is still a member of the current object, and I'm pretty sure there's no way "this." could make a difference there, right?
        • tjalfi 1338 days ago
          You're correct that the presence or absence of a "this." shouldn't make a difference.

          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.

    • bradjohnson 1343 days ago
      In addition to static imports, static fields and functions that belong to the instantiated class are not members of the current object.
  • drfrank 1344 days ago
    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.

  • kolbe 1344 days ago
    > 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.

  • sebazzz 1344 days ago
    > 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.

        public class MyClass : YourClass {
            public void MyMethod() {
                  if(!base.YourMethod()) return;
            }
        }
    
    That is some dangerous advice! If you later decide to override the base class method, you're in for a treat! The non-overridden behavior is then used.

    My rule is exactly the opposite. Only allow `base` in:

    - Constructors

    - Overrides

    • jermaustin1 1344 days ago
      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.

  • tantalor 1344 days ago
    > I've had managers want developers...

    What does being a manager have to do with code style? This is textbook micromanagement.

  • alkonaut 1344 days ago
    Prefixing "this.field" is nicer looking than "_field" for signifying a field rather than a local or parameter (These days most syntax highlightrs should be clever enough to distinguish this by color, but in the past this was useful. As an added benefit autocomplete will be triggered after "this.".

    > But even in this case, you should really be using Pascal casing as per Microsoft's Capitalization Conventions

    Not sure what this is refering to. In assignmenmt this.foo = foo, both the field and the parameter should have the same casing, that's why "this.foo" is needed to distinguish the field from the parameter.

    In the end, these are mostly cosmetic/style choices. Consistency matters more than whatever style is chosen, but I of course find it very important that we agree on my preference.

  • jermaustin1 1344 days ago
    Wow. I didn't think this post would cause so much controversy, since these "opinions" are shared by Visual Studio 2017 and above [1]

    1: https://i.imgur.com/9F6Lyx8.png

  • oaiey 1344 days ago
    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.

    I understand his suffering :)

    • crc32 1344 days ago
      StyleCop on the other hand - a freely available linter as opposed to the commercial resharper - mandates the use of `this` by default.
  • nurettin 1344 days ago
    It isn't about consistency or style. People use "this." to start their intellisense autocomplete which brings up the most used methods depending on the context.
  • specialist 1344 days ago
    I recently listened to a 2015 interview with David Ungar, of Self, Smalltalk, and misc fame. https://www.youtube.com/watch?v=8nfrC-YLYqc

    Amongst other gems was a nice reminder about Self's innovation in eliminating the 'self.' prefix (or equiv). It's in the name, right? Can't believe I forgot that.

    I'm surprised no successor (to Self, Java, or both) has eliminated (disallowed) variable aliases. So that local and instance variables cannot have the same name. Voila. One category of errors completely eliminated.

    --

    Any and all use of 'this.' prefixes is a full stop hard omega fail. For both the language and any user of that language.

    Whatever else I think of JavaScript, the lack of intrinsic identitiers (name?) should have immediately disqualified the language and prevented any further consideration.

    Huge disappointment that TypeScript did not address this original sin. (Haha, nerd joke, I slay me.)

    This OP gives example of this.method(...). What? Is that a C# thing? Why would anyone do that?

    Oh well. Let's go back to arguing about dynamic vs static typing.

  • balfirevic 1344 days ago
    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.

  • cgrealy 1344 days ago
    Honestly, I really don’t care. It’s (at most) a 5 minute conversation between leads on a new repo. Either use this. or an _ prefix or whatever.

    Then set it as a global rule in .editorconfig (or whatever equivalent tool you’re using) and never think about it again

  • SigmundA 1344 days ago
    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.

  • dleslie 1344 days ago
    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.
    • asdfman123 1344 days ago
      I sometimes type "this." to get some help from Intellisense but I then delete the prefix after I find what I need.
  • programmarchy 1344 days ago
    If it was incorrect, the compiler, or at least the linter, would throw an error or at least a warning, no?

    Developers would be wise not to mistake reified opinions with correctness.

    • jermaustin1 1344 days ago
      Visual Studio 2017 and above actually does complain about it. It will recommend removing `this` from your code.
      • jasomill 1344 days ago
        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.

        • jermaustin1 1344 days ago
          > 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.

      • crc32 1344 days ago
        I don't think this is true - sounds like resharper, an extension for Visual Studio. I don't think this is the default out of the box.
  • klodolph 1344 days ago
    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.

  • elboru 1344 days ago
    I can think of some readability benefits of using ‘this’. But the author didn’t give further details on why he didn’t like it.

    Is it just a matter of taste?

    • jermaustin1 1344 days ago
      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.
    • algorithmsRcool 1344 days ago
      It is entirely about taste except for his mention of correctness between 'base' and 'this'.
  • Meph504 1343 days ago
    You mistate "incorrectly" for "in a way I don't like. "

    Don't get me wrong, it often annoys me to see it over used, but it isn't incorrect, and the assertion that visual studio recommends removing it isn't really strong supporting evidence, as you know it recommends changing plenty of things, that are perfectly acceptable.

  • asveikau 1344 days ago
    I had a colleague who would like to put "this" on member accesses so that it was absolutely clear from a glance that it was a member access and not something local.

    Similar to people who use a prefix like "m_" or an extra underscore or capitalization scheme for member names.

    These are all matters of opinion and style and no one thing is correct.

  • jagged-chisel 1344 days ago
    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.
  • self_awareness 1344 days ago
    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.
    • idemprotent 1344 days ago
      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.
      • self_awareness 1343 days ago
        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.

  • icholy 1343 days ago
    > I've had coworkers who would put this before every method call, because...?

    Because then I can tell it's a method by only looking at the call site.

  • caseymarquis 1344 days ago
    The author is complaining about explicit use of 'this' where it's not required. It's hardly incorrect, it's a preference. I'd personally pick explicit use of this if I cared enough be consistent about it. I've specifically been bitten by refactoring a local variable to the same name as a private variable on accident, and shadowing the private variable within the local scope. Using explicit this prevents that from happening.

    Now, if you want an example of incorrect C#, I'm sure I can find something I've got running in production much worse than explicit this...

    Posting from mobile, so formatting might have issues, but below I'm monkey patching a bug out of the immutable AST Entity Framework generates when using SQL Server's DateDiff function. On the one hand it's truly monstrous. On the other hand, it's saved hundreds of lines of code elsewhere in the application.

            public static IQueryable<IGrouping<TKey, TSource>> GroupByDateDiff<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector) {
                var body = (NewExpression)keySelector.Body;
                foreach (var arg in body.Arguments) {
                    if (arg.NodeType == ExpressionType.Call) {
                        var callNode = (MethodCallExpression)arg;
                        if (callNode.Method.Name == "DateDiff") {
                            var dateDiffFirstArg = callNode.Arguments[0];
                            if (dateDiffFirstArg.NodeType == ExpressionType.Constant) {
                                //It was already a constant, so we're good.
                            }
                            else {
                                //HACK: This will break if the internal implementation of ReadOnlyCollection changes.
                                var listInfo = typeof(ReadOnlyCollection<Expression>).GetField("list", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                                var list = (IList)listInfo.GetValue(callNode.Arguments);
                                if (dateDiffFirstArg.NodeType == ExpressionType.MemberAccess) {
                                    list[0] = Expression.Constant((string)GetMemberValue((MemberExpression)dateDiffFirstArg));
                                }
                                else {
                                    throw new ArgumentException($"{nameof(GroupByDateDiff)} was unable to parse the datePartArg argument to the DateDiff function.");
                                }
                            }
                        }
                    }
                }
                return source.GroupBy(keySelector);
            }
  • thelazydogsback 1344 days ago
    "this" is not just superfluous -- if you use it, you lose the referential transparency of the call. If you don't use "this" you can change where your call is implemented to any of these places without refactoring all the calls:

    - In current class

    - In a base class

    - A static method in the current class

    - A "static import"ed helper method from outside the class

    In the past I'd say you could use it to be self-documenting, but these days you have semantic colorizing, tooltips, etc., for this sort of discovery if you want it.

    • ddek 1344 days ago
      No?

      If your call is implemented in the current class, the 'this' is implicit.

      If the call is implemented in a base class, and not overriden, the base class method is still available through the 'this' keyword. If you do override the base method, you must explicitly do so. Why you would want to call the base in a class which overrides it, I don't know.

      Static methods in the same class are impossible. You can't have two methods with the same signature, static or otherwise.

      Extension methods are different, but there is clear precedence. The instance method is used before the extension. 'this.ExtensionMethod()' is still valid, so you aren't getting any of this referential transparency.

      In any case, the only use case for 'this' is to call extension methods from within a class the extension is defined for. It certainly does not give any referential transparency.

      • thelazydogsback 1343 days ago
        I'm not sure I'm following your objections at all - if this is implicit, then you don't need it, correct?

        > Static methods in the same class are impossible. You can't have two methods with the same signature, static or otherwise.

        I never said anything about having both at once -- I was talking about refactoring - changing the location of where the fn was defined - from a method to a static. (As one does if it turns out you're not using any object state.) Of course, some languages let you call static's on the same class with 'this' and some can only reference instance methods.

  • theandrewbailey 1344 days ago
    Does using 'this' everywhere break subclass overrides?
    • sebazzz 1344 days ago
      No, but using `base` does, and he advocates for using `base`:

      > 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.

          public class MyClass : YourClass {
              public void MyMethod() {
                  if(!base.YourMethod()) return;
              }
          }
      • jermaustin1 1344 days ago
        I don't advocate for using base instead of this.

        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

        • bradjohnson 1344 days ago
          You're advocating using base.foo() rather than this.foo() which is not equivalent behaviour and is bad advice.
          • jermaustin1 1344 days ago
            Incorrect. I am advocating that if you want to signify you are using the base classes method, use base. Otherwise don’t use base or this.
        • mypalmike 1344 days ago
          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".
          • jermaustin1 1344 days ago
            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.

    • drchickensalad 1344 days ago
      Nope. Virtual and non-virtuals behave exactly how you'd expect, other than obviously you still need to use base instead when desired.
    • Akronymus 1344 days ago
      No, as "this" works on a object basis.
  • ashleyn 1344 days ago
    laughs in JavaScript
  • spacekitcat 1344 days ago
    I'm afraid it's bike sheds all the way down.
  • fistfucker3000 1344 days ago
    You seem awful to work with