A class is a type you define: it groups data (fields) with the code that works on that data (methods). An object is one instance of a class, created at run time with new. One class, many objects, each with its own values.
Declaring a class and creating objects
A class declaration lists its members inside braces. Fields hold the data, methods hold the behavior. new ClassName() allocates an object and gives you a reference to it.
Output:
Maya: 120.50
Omar: 40
Withdraw 200 succeeded: False
Each object has its own Owner and Balance. Inside a method, Balance means "the balance of the object this method was called on", which is why maya.Deposit and omar.Deposit change different numbers. That implicit object is available as this when you need to name it.
Fields that you do not assign start at their default value: 0 for numbers, false for bool, and null for strings and other class types.
The members here are public so Main can reach them. Real classes usually keep fields private and expose properties instead, and the access modifiers page has the rules. A class can also declare a constructor to set its fields when the object is created, covered on the constructors page.
A class is a reference type
A variable of a class type does not contain the object. It contains a reference to an object that lives on the heap. Assigning the variable copies the reference, so two variables can point at the same object.
Output:
5
6
True
False
Three consequences show up here:
- Changing the object through
secondis visible throughfirst, because there is only one object. - Passing an object to a method passes the reference. The method can change the object's fields and the caller sees it. (Assigning a new object to the parameter inside the method does not affect the caller's variable; that needs
ref.) ==on two class instances compares references by default: "is this the same object?", not "do these have the same values?".lookalikehas identical data and is still a different object.
If you want copies on assignment and value comparison, look at structs, which are value types, or records, which compare by value.
null and NullReferenceException
A reference variable can hold null, meaning "no object". Using a member through null throws NullReferenceException, the most common runtime exception in C# code.
Output:
True
no city on file
NullReferenceException: Address was never set
Lisbon
The fix is almost never to catch the exception. Find out why the reference is null and either create the object earlier, check before use, or use the null-conditional operator ?., which stops and yields null instead of throwing. ?? then supplies a fallback. Both operators are covered in nullable types.
Overriding ToString
Every class inherits from object, which provides ToString(). The inherited version returns the type's full name (including its namespace, if it has one), which is rarely what you want to print. Override it:
Output:
Plain
Mug (8.50)
In cart: Mug (8.50)
Total line: Mug (8.50)
Console.WriteLine, string interpolation and + with a string all call ToString() for you. The debugger also shows it, which makes an override useful even when you never print the object yourself.
Object initializers
An object initializer sets public fields and properties right after the object is constructed, in the same expression. It reads better than a list of assignments and works well inside collection literals.
Output:
A12: 25 (0 extras)
A13: 40 (2 extras)
Two details in the second ticket. Price = 40m overrides the field initializer's 25m, because the object initializer runs after the object is built. Extras = { "Parking", "Poster" } has no new: it calls Add on the list the field already holds, rather than replacing it.
An object initializer is not a constructor. It can only set members that are accessible from the calling code, and it cannot enforce that a member is set at all. When an object is invalid without certain values, require them in a constructor.
Partial classes
The partial keyword splits one class across several files. The compiler merges the parts into a single class.
// Invoice.cs
public partial class Invoice
{
public decimal Subtotal;
public decimal Total() => Subtotal + Tax();
}
// Invoice.Tax.cs
public partial class Invoice
{
private decimal Tax() => Subtotal * 0.2m;
}
Every part must say partial, be in the same namespace and the same project. The common use is generated code: WinForms designers, source generators and some ORMs write one part and leave the other to you, so regenerating never overwrites your code. Splitting a hand-written class across files only to make it shorter usually hides a class that should be two classes.
Common mistakes
- Using an object before creating it. A field of class type is
nulluntil you assignnew ...to it. The first member access throwsNullReferenceException. - Expecting assignment to copy.
var b = a;for a class gives a second name for the same object. Create a new object and copy the values when you need an independent one. - Comparing objects with
==and expecting value comparison. For classes it compares references unless the class overloads==(asstringdoes). Compare the relevant fields, or overrideEquals. - Printing an object and getting its type name. Override
ToString(). - Declaring everything
public. It works in small examples, but it lets any code put the object into an invalid state, for example a negative balance. Keep fields private and change them through methods that check the rules.
Frequently Asked Questions
What is a class in C#?
A class is a type you define: a named group of data (fields and properties) and behavior (methods). class Account { public decimal Balance; public void Deposit(decimal amount) { Balance += amount; } } declares one. A class is a blueprint; it does nothing until you create objects from it with new.
What is the difference between a class and an object in C#?
The class is the definition, written once in source code. An object is one instance of it, created at run time with new, with its own copy of every instance field. new Account() twice gives two objects of the same class with independent balances.
How do you create an object in C#?
Use new followed by the class name and constructor arguments: var account = new Account();. You can set public fields and properties in the same expression with an object initializer: new Account { Owner = "Maya" }. The variable holds a reference to the new object, not the object itself.
Why do I get a NullReferenceException in C#?
You used a member (.Name, .Length, a method call) through a variable that holds null, so there is no object to act on. Common causes are a field that was never assigned (class fields start as null), a lookup that returned null, or a method that returned null on failure. Check with if (x != null), use x?.Name, or make sure the object is created before use.
How do I override ToString in C#?
Declare public override string ToString() in your class and return the text you want, for example public override string ToString() => $"{Name} ({Price:F2})";. Without it, Console.WriteLine(obj) and string interpolation print the class name, because that is what object.ToString() returns.