C# Properties, Fields, and Methods Explained with Examples
A clear, practical guide to C# fields, properties, and methods in 2026: what each one is for, when to use which, and how to design clean classes you will not hate in six months.
Open any real C# class and you will see three kinds of members: fields (plain variables that hold the data), properties (a controlled way to read and write that data), and methods (the things the class actually does). Get the relationship between the three right and your code will read clearly six months from now. Get it wrong and even small classes turn into a mess.
This guide explains exactly what each one is, when to choose which, and how the modern 2026 patterns — including the new field keyword in C# 14 — change the day-to-day defaults. If C# itself is brand new, start with What is C#? A Beginner's Guide to .NET Development in 2026 first.
Fields: Where the Data Actually Lives
A field is a variable declared inside a class. It holds the state of one particular object.
public class Order
{
private string _id;
private decimal _total;
}Fields are usually private — only the class itself touches them. Adding readonly means the value can only be set in the constructor, which is the right default for anything that should never change after the object is built. The leading underscore is a common convention to mark "this is a backing field, not a property."
Public fields exist but are almost always a mistake. They give the outside world direct access to your internal storage, so the moment you decide to add validation or computed logic, every caller breaks. Use a property instead.
Properties: Controlled Access to Data
A property is a field with a gatekeeper. From the outside it looks like a variable; on the inside it is two methods (get and set) the compiler generates for you.
public class Order
{
public string Id { get; } // read-only auto-property
public decimal Total { get; private set; } // public read, private write
public int Quantity { get; set; } // full read/write
public Order(string id) { Id = id; }
}Three patterns to recognise:
{ get; }— read-only after construction. Set once in the constructor.{ get; private set; }— public can read; only the class itself can change it.{ get; set; }— full read/write. Use sparingly; usually means you should rethink the design.
Auto-properties are the default. The compiler quietly creates a hidden backing field for you. The day you need real logic — validation, lazy initialisation, raising an event when the value changes — you switch to a property with an explicit body without changing a single caller. That is exactly why properties exist.
The New field Keyword (C# 13/14)
For years, the moment you needed any logic in a setter you had to declare your own backing field, name it, and remember the underscore. C# 13 added a field contextual keyword that gives you the auto-generated backing field by name.
public string Email
{
get;
set => field = value?.Trim().ToLowerInvariant() ?? throw new ArgumentNullException();
}You skip the explicit private string _email; declaration and let the compiler manage the storage. Reach for it any time you want a tiny custom setter without all the boilerplate. Available in C# 13 and refined in C# 14 — the version shipping with .NET 10 LTS.
Methods: The Behaviour
A method is a function attached to a class. It reads or modifies the object's state and returns a value (or void if it does not).
public class Order
{
public string Id { get; }
public List<Item> Items { get; } = new();
public decimal Subtotal => Items.Sum(i => i.Price * i.Quantity);
public Order(string id) { Id = id; }
public void Add(Item item) => Items.Add(item);
public bool TryGet(string sku, out Item? item) => (item = Items.FirstOrDefault(i => i.Sku == sku)) is not null;
}
public record Item(string Sku, string Name, decimal Price, int Quantity);Notice the => (expression-bodied) syntax. When a method or property body is a single expression, drop the braces and the return. It reads better and the compiler generates the same IL.
Subtotal here is interesting: it is a property whose get runs every time you ask for it. If something is cheap to compute and changes when other state changes, prefer a computed property over a stored field — you cannot get them out of sync.
When to Use Which
The 2026 rule of thumb almost everyone converges on:
| You want... | Use |
|---|---|
| Simple read-only data | public T X { get; } (set in ctor) |
| Read/write data with no logic | public T X { get; set; } |
| Data with validation or normalisation | property with field keyword |
| Internal storage no one else should see | private (or private readonly) field |
| A value derived from other state | computed property => ... |
| Behaviour (does something, returns a result) | method |
| Pure data transfer object | record (which is mostly properties) |
If a class has any "do something" verbs — Submit, Calculate, Add, Reload — those are methods. Everything else is a property or a field.
A Real Example
Putting it together:
public class Customer
{
public Guid Id { get; }
public string Name { get; private set; }
public string Email
{
get;
set => field = value?.Trim().ToLowerInvariant() ?? throw new ArgumentNullException();
}
private readonly List<Order> _orders = new();
public IReadOnlyList<Order> Orders => _orders;
public Customer(string name, string email) { Id = Guid.NewGuid(); Name = name; Email = email; }
public void Rename(string name) => Name = name;
public Order PlaceOrder() { var o = new Order(Guid.NewGuid().ToString()); _orders.Add(o); return o; }
}Id is read-only. Name is publicly readable but only Rename can change it (control point for logging or validation later). Email normalises on write. Orders exposes a read-only view of an internally mutable list. PlaceOrder is the only way to add an order. The class is impossible to put into an invalid state from outside.
Common Mistakes Beginners Make
- Making fields
public. Use auto-properties instead. - Writing custom
get/setfor every property when an auto-property would do. - Exposing a
List<T>directly. ExposeIReadOnlyList<T>and let methods mutate the underlying list. - Confusing methods and properties. If it has side effects or runs noticeably long, it should be a method (so callers know it costs something).
- Using
Newtonsoft.Jsonattributes on properties. The built-inSystem.Text.Jsonis the modern default.
Quick Reference
- Field:
private readonly T _x;— internal storage - Auto-property:
public T X { get; set; }— exposed storage with a hidden backing field - Read-only auto-property:
public T X { get; }— set in ctor only - Computed property:
public T X => expr;— derived value, no storage - Method (expression-bodied):
public T Do() => expr; - New
fieldkeyword (C# 13/14):set => field = value?.Trim(); - Records for value classes:
public record Money(decimal Amount, string Currency); - Use
IReadOnlyList<T>/IReadOnlyDictionary<TK,TV>to expose collections without giving up control
Rune AI
Key Insights
- Default fields to
private readonly; expose data through properties, not public fields. - Use auto-properties (
{ get; set; },{ get; private set; },{ get; }) until you genuinely need logic. - The new
fieldkeyword in C# 13/14 lets you write small custom setters without an explicit backing field. - Use computed properties for derived values; methods for actions and side effects.
- Expose collections as
IReadOnlyList<T>orIReadOnlyDictionary<TK,TV>and mutate them through methods.
Frequently Asked Questions
What is the difference between a field and a property?
Should every property have a setter?
When should I use a method vs a property?
What is the new `field` keyword?
Should I prefer records over classes?
Conclusion
Fields hold the data. Properties expose it safely. Methods are the actions. Get those three roles clear in your head and a C# class becomes easy to design and easy to read. Build the Customer example above, then turn it into a small console app — the patterns scale from a five-line script to a production microservice without changing.