Last Updated: May 22, 2026
Inside an instance method or constructor, this is a reference to the object the method is running on. It sounds abstract, but it solves a few very concrete problems: telling a field apart from a parameter with the same name, handing the current object to another method, and chaining method calls so they read like a sentence. This lesson covers what this actually points to, where you have to write it, where the compiler fills it in for you, and where it isn't allowed at all.
this Refers ToEvery instance method and constructor in C# has an implicit first argument: a reference to the object the call was made on. C# exposes that reference through the keyword this. When you call cart.AddItem(...), inside AddItem the keyword this is the cart you called it on.
Same method, same code, different this. When aliceCart.PrintOwner() runs, this is aliceCart. When bobCart.PrintOwner() runs, this is bobCart. The method has no other way to know which object it was called on, because the body itself is shared across every Cart instance.
Think of this as a hidden parameter that gets filled in by the call. The compiler turns cart.AddItem(item) into something close to AddItem(cart, item) internally. The first argument is what you see as this inside the method.
This is also why this only makes sense in instance code. There is no current instance in a static method or in a static field initializer, and we'll see what happens when you try.
The most common reason to type this explicitly is to break a name collision between a field and a parameter. When both have the same name, the parameter wins in the local scope, and this.fieldName is the only way to get to the field.
Inside the constructor, plain name resolves to the parameter, and this.name resolves to the field. Without this., the line would read name = name, which assigns the parameter to itself and leaves the field at its default (null for string). That's a real bug, and modern compilers warn about it with CS1717 ("Assignment made to same variable; did you mean to assign something else?"), but the warning is easy to ignore.
There are two schools of thought here. Some teams prefer matching parameter names so the constructor reads naturally, and accept that they have to type this. on every assignment. Other teams use a different naming convention for private fields, usually a leading underscore (_name, _price), which sidesteps the collision entirely.
Both styles compile to the same thing. The leading-underscore convention is widely used in .NET and is what the official .NET runtime source uses for private fields. The this.-everywhere style is the default in many C# textbooks. Pick one and stay consistent inside a codebase.
Name collisions happen with properties too, but properties are typically PascalCase (Name, Price) and parameters are camelCase (name, price), so they don't collide. The collision problem is really a private-field-vs-parameter problem.
None at runtime. this.field and a plain _field compile to the same IL. The choice is purely about readability and team convention.
this to Other Methodsthis is a real reference. You can pass it to another method, store it in a field, or return it from a property. This shows up whenever an object needs to hand itself to a collaborator, for example to register with a manager or to add itself to a list.
The constructor calls tracker.Track(this) and the brand-new Order flows into the tracker's list. From that point on, the tracker holds a reference to the object, which means the garbage collector cannot reclaim it as long as the tracker is alive. This is worth flagging.
Handing this to an outside object creates a reference the GC has to respect. If the receiver is long-lived (a static cache, a singleton manager, an event bus), the object you registered will live as long as that receiver does. This is a common source of memory leaks in event-driven UIs. The Memory Management section covers how to break the chain (with IDisposable or weak references).
Another everyday use is comparing the current instance to another one. The standard Equals(object?) override almost always starts by comparing to this:
ReferenceEquals(this, other) asks "are these two names for the same object on the heap?" It's a fast path that skips the rest of the comparison when the answer is obviously yes. The _Equals() & GetHashCode()_ lesson covers them in detail; the point here is just that this is a regular reference you can hand to any method that takes an object.
return thisA method that returns this lets the caller chain calls on the same object. The pattern is called fluent because the resulting code reads close to an English sentence.
Each method does its work and returns the same CartBuilder instance via return this. The next call in the chain operates on that same object, not a new one. The whole chain mutates one CartBuilder from top to bottom.
A few details. The return type of every chainable method is CartBuilder, not void. The order of calls matters: ApplyDiscount(0.10m) runs after both AddItem calls, so it applies to the full $99.98 subtotal, not to each item. And the chain ends with Print(), which returns void and terminates the chain naturally.
This is the same pattern you see in StringBuilder.Append, LINQ's Where/Select/OrderBy, and most builder APIs in .NET. The element that makes them work is one short line: return this.
Fluent chains are a stylistic choice, not a correctness one. They work well when you have a sequence of small configuration calls. They become confusing when individual methods do too much, or when readers can't tell at a glance which calls mutate the object and which return a new one. For an immutable builder (returning a new object each time), the pattern is the same but return this becomes return new CartBuilder(...).
The flow of references during a chained call. Each return this hands the same object back to the next call:
Every node in the middle hands the same CartBuilder reference forward. There is only ever one object on the heap; the chain just keeps calling methods on it.
this[...]: IndexersThe keyword this also has a special role in class declarations: it names the indexer. An indexer lets instances of your class be accessed with the [index] syntax, just like an array. The declaration uses this because the indexer "belongs to" the current instance and acts like a property without a name.
The indexer declaration public string this[int index] reads as "for any instance of this class, allow [int index] to be applied to it." Inside the get and set accessors, you write the logic that maps the index to whatever storage the class actually uses, here a plain array. value is the value being assigned in the set, just like a property setter.
Indexers are not limited to integer indices, and they're not limited to one index. A catalog keyed by product name might use a string indexer:
The Smartwatch lookup returns 0m because the indexer's get falls back to the default when the key is missing. That's a deliberate design choice; an alternative would be to throw KeyNotFoundException, like Dictionary<TKey, TValue> does directly.
Indexers can also take more than one parameter, which is how multi-dimensional access works:
You'd write grid[2, 3] to read or write. Properties don't allow multiple parameters; only indexers do.
This is just an introduction; indexers, their access modifiers, and IList<T>.this[int] are covered in more depth in the Encapsulation section. The key takeaway here is that the keyword this is doing double duty in C#: inside a method it's the current instance, and inside a class declaration this[...] declares an indexer.
thisYou almost never have to write this. to access a member; the compiler fills it in for you. The exception is the name collision we already saw, plus a few stylistic situations. When two references to a member are equivalent in behavior, which one should you actually type?
Both forms compile to the same IL. The compiler doesn't care. The reasonable defaults inside the C# community are:
| Situation | Use this.? |
|---|---|
| Field and parameter have the same name | Yes, required to reach the field |
| Passing the current instance to another method | Yes, you have to spell it out |
| Returning the current instance for fluent chaining | Yes, return this |
| Indexer declaration | Yes, it's the keyword |
| Plain access to a field with no collision | No |
| Plain call to another instance method | No |
The deeper question is: when does a member access need a qualifier at all? In C#, name resolution inside an instance method looks in this order:
thisusing staticIf step 1 finds a hit, steps 2-4 are not consulted. That's why a parameter named price shadows a field named price. Writing this.price skips step 1 entirely and goes straight to the member lookup, which is why the qualifier disambiguates.
The diagram is the rule that decides whether this. is needed. Most of the time the answer is "no", because the field name doesn't match any local. The classic case where the answer is "yes" is the constructor parameter that mirrors a field name.
A style note: some teams require this. everywhere as a coding rule, because it makes "is this a field or a local?" obvious at a glance. Others find it noisy and avoid it except where the compiler forces them. Visual Studio's analyzers can enforce either choice. The C# language and runtime do not care; pick what reads best for your team and apply it consistently.
this Doesn't Exist in Static MethodsA static method belongs to the type, not to any particular instance. There is no "current object" to refer to, so there's no this. Trying to use it produces a compiler error.
The error is CS0026: "Keyword 'this' is not valid in a static property, static method, or static field initializer." The same restriction applies to:
static void Print())static int Count { get; })static Cart() { ... })static int Count = ???;)The error makes sense once you remember the mental model from earlier: this is an implicit first argument that gets filled in by a call like cart.Method(). A static call doesn't have a target object on the left of the dot. You write Cart.Print(), not someCart.Print(). There is nothing for the compiler to pass as the this argument.
This also means a static method can't directly read or write instance fields and properties. If a static method needs to operate on an instance, the instance has to be passed in explicitly as a parameter:
Cart.Sum is static and accesses Total only through the explicit Cart parameters. Inside this method, there is no this, and you can see that there's no way one could be useful: you have two carts, and "current cart" is meaningless.
The flip side is also useful to remember: an instance method can call a static method, because the static method just doesn't need a this. A static method cannot call an instance method on the same class without an instance in hand, because the instance method needs a this to operate on. This asymmetry trips up beginners who write a static helper that wants to read this.Total and can't figure out why the compiler refuses.
If you find yourself wanting this inside a static method, ask: does this method really need to be static? If it conceptually operates on a single instance, make it an instance method. If it does need to be static (it's a factory, a helper that operates on multiple instances, a pure function), pass the instance in as a parameter and use it explicitly.
A small end-to-end example that uses this in four different roles: disambiguating a constructor, passing the current instance to a collaborator, returning this for chaining, and an indexer.
Four uses of this in fewer than fifty lines: this.customer resolves the name collision in the constructor; return this keeps the chain going through three Add calls; this[i] inside Print calls the indexer on the current cart; and registry.Track(this) hands the cart over to the registry. None of them are tricky in isolation. Combined, they cover most of what this is used for in everyday C# code.