This closes Module 2: until now, every book in BiblioTechConsola was a handful of loose
variables (a string for the title, another for the author, another for the ISBN, a bool
for availability) that had to be declared and kept in sync by hand, once per book. If
BiblioTech managed a hundred books, that would mean four hundred variables — or four parallel
arrays where position i in each one had to correspond to the same book, with the constant
risk of them falling out of sync. In this Module 3: Object-Oriented Programming you'll fix
that problem at its root by learning to define your own types: classes. A class groups
together, in a single place, the data (properties) and, later on, the behavior (methods) of a
real-world concept — a book, a member, a loan — so that each book in BiblioTech becomes a
single self-contained object instead of four scattered variables. This first lesson lays the
groundwork: what a class is, what an object is, how to define a class with properties, and how
to create objects from it with new.
Contents
- From loose variables to objects: why classes
- What is a class? What is an object?
- Defining a class with the
classkeyword - Fields and properties (
{ get; set; }) - Creating objects with
new - Object initializers
- Multiple objects of the same class
- Classes versus primitive types: reference types
- From loose variables to objects: why classes
Recall how a book was represented in the previous modules:
string bookTitle1 = "One Hundred Years of Solitude";
string bookAuthor1 = "Gabriel Garcia Marquez";
string bookIsbn1 = "978-84-376-0494-7";
bool bookAvailable1 = true;
string bookTitle2 = "Hopscotch";
string bookAuthor2 = "Julio Cortazar";
string bookIsbn2 = "978-84-376-0495-4";
bool bookAvailable2 = false;Notice the problem: nothing in the code indicates that bookTitle1, bookAuthor1,
bookIsbn1 and bookAvailable1 belong to the same book; that's a convention that only
exists in the programmer's head, held together by carefully naming each variable. Adding a
third book means copying and pasting four more lines with the name Book3, and trusting
yourself not to make a mistake. This module solves this by grouping those four pieces of data
into a single type called Book, so that each real book in the library is represented by
a single object.
- What is a class? What is an object?
A class is a template (or "blueprint") that describes what data and what behavior the objects created from it will have. It is not, by itself, a specific book: it is the definition of "what a book is and what it can do" in the system. An object is a concrete instance of a class: a real book, with its own values for the title, the author, the ISBN and the availability.
The relationship between a class and an object is the same as between a house blueprint and the houses built from it:
| Concept | Analogy (house blueprint) | In BiblioTech |
|---|---|---|
| Class | The blueprint: defines that every house has doors, windows, rooms | Book: defines that every book has a title, author, ISBN, availability |
| Object | A specific house, built following the blueprint | A specific copy, for example "Hopscotch" |
| Multiple objects | Many different houses, built from the same blueprint | Many different books, all sharing the same structure |
From a single blueprint you can build as many houses as you like, each with its own address and its own furniture; from a single class you can create as many objects as you like, each with its own values.
- Defining a class with the
class keyword
class keywordA class is defined with the class keyword followed by a name (by convention, in
PascalCase, starting with a capital letter) and a body between braces { }:
This is already a valid class, although still empty: it doesn't describe any data yet. The next step is to state what information each book holds.
Naming convention: classes in C# are named in
PascalCase(Book,Member,Loan), unlike variables and parameters, which usecamelCase(title,memberNumber). This course will follow this convention strictly from now on.
- Fields and properties (
{ get; set; })
{ get; set; })Inside a class, data can be represented in two ways: fields and properties.
A field is the simplest form: a variable declared directly inside the class.
However, in C# the usual — and recommended — approach is to use properties, which are
declared similarly to a field but include { get; set; } afterward:
class Book
{
public string Title { get; set; }
public string Author { get; set; }
public string Isbn { get; set; }
public bool Available { get; set; }
}This syntax is called an auto-implemented property: get lets you read the value, and
set lets you assign it, without you having to write the code that stores the data internally
(the compiler generates that hidden storage for you). For practical purposes, right now they
behave just like a public field, but with two important advantages that will make more sense
throughout the module:
- Its name is written in
PascalCase(Title, nottitle), following C# convention for anything visible from outside the class. - Later on (in the Encapsulation lesson) you'll be able to add validation logic inside the
setwithout changing how the property is used from the outside — something a public field doesn't allow you to do cleanly.
Field (public string title;) |
Property (public string Title { get; set; }) |
|
|---|---|---|
| Syntax | Variable declared directly | Adds { get; set; } |
| Naming convention | camelCase |
PascalCase |
| Allows adding validation later without breaking code that uses it | No, not cleanly | Yes |
| Recommended use in C# for publicly exposed data | No | Yes |
From now on, Book (and the rest of the classes in the course) will always be defined with
properties, not with loose public fields.
This will be the starting definition of Book for the entire module:
class Book
{
public string Title { get; set; }
public string Author { get; set; }
public string Isbn { get; set; }
public bool Available { get; set; }
}
- Creating objects with
new
newDefining the Book class doesn't create any book yet: it only describes what any book will
look like. To create a concrete object — an instance — you use the new keyword,
followed by the class name and parentheses:
Book book1 = new Book();
book1.Title = "One Hundred Years of Solitude";
book1.Author = "Gabriel Garcia Marquez";
book1.Isbn = "978-84-376-0494-7";
book1.Available = true;
Console.WriteLine(book1.Title); // One Hundred Years of Solitude
Console.WriteLine(book1.Available); // TrueLet's break down this key line: Book book1 = new Book();
Book(before the variable name) indicates the type of the variablebook1: it will be an object of typeBook.new Book()creates a new object in memory, following theBookclass template, and returns a reference to it.book1is the variable that holds that reference, and from then on the.(dot) operator is used to access its properties:book1.Title,book1.Author, etc.
Every property of an object just created with new Book() takes its default value until
one is explicitly assigned to it: null for string (which is why you must assign it before
using it, or the program will fail when reading it), false for bool, 0 for numeric types
such as int.
- Object initializers
Assigning each property on a separate line, as in the previous example, works but is
repetitive. C# offers a more compact alternative called an object initializer, which
assigns several properties between braces { } right after new Book():
Book book2 = new Book
{
Title = "Hopscotch",
Author = "Julio Cortazar",
Isbn = "978-84-376-0495-4",
Available = false
};
Console.WriteLine(book2.Title); // HopscotchThis code is equivalent to creating the object with new Book() and then assigning each
property separately, but it's more readable when initializing several properties at once,
since it visually groups "these values belong to this object."
- Multiple objects of the same class
The advantage over the loose variables from Module 1 is best appreciated with several books
at once: each Book object is completely independent from the others, even though it shares
the same structure defined by the class.
Book book1 = new Book { Title = "One Hundred Years of Solitude", Author = "Gabriel Garcia Marquez", Isbn = "978-84-376-0494-7", Available = true };
Book book2 = new Book { Title = "Hopscotch", Author = "Julio Cortazar", Isbn = "978-84-376-0495-4", Available = false };
Book book3 = new Book { Title = "Ficciones", Author = "Jorge Luis Borges", Isbn = "978-84-376-0496-1", Available = true };
Console.WriteLine($"{book1.Title} - Available: {book1.Available}");
Console.WriteLine($"{book2.Title} - Available: {book2.Available}");
Console.WriteLine($"{book3.Title} - Available: {book3.Available}");Each of the three objects (book1, book2, book3) has its own values for Title, Author,
Isbn and Available, with no possibility of confusing the title of one with the availability
of another: all the information for a specific book lives inside its own object. Modifying
book2.Available doesn't affect book1 or book3 in any way.
- Classes versus primitive types: reference types
An important difference between a Book and a primitive type such as int or bool is that
classes are reference types: a variable of type Book doesn't contain the object itself,
but a reference (a kind of "address") pointing to it in memory. This has a practical
consequence worth seeing from the start:
Book original = new Book { Title = "Hopscotch", Available = true };
Book copy = original; // copy is not a new book: it points to the SAME object as original
copy.Available = false;
Console.WriteLine(original.Available); // False -- the original changed too!Since copy and original point to the same object in memory, modifying copy.Available
is also reflected when reading original.Available: they are not two independent books, they
are two different names for the same book. This contrasts with primitive types (int,
bool, double...), which are value types: when you write int b = a;, b receives an
independent copy of the value of a. We'll revisit this distinction in more detail in the
last lesson of the module, when we compare classes with struct.
Common Mistakes and Tips
- Forgetting
new: writingBook book1;declares a variable capable of referencing aBook, but doesn't create any object; trying to usebook1.Titlebefore assigning itnew Book()causes a compilation error (or, in certain contexts, a runtime exception if the variable isnull). - Confusing the class with the object:
Bookis the template;book1,book2,book3are concrete objects created from it. It's a common mistake in early lessons to talk about "the classbook1" when it's actually an object. - Using loose public fields out of habit: in C# properties (
{ get; set; }) are preferred over public fields, precisely because they allow adding validation later without breaking code that already uses them. Get used to this syntax from now on. - Not internalizing that classes are reference types: as seen in the last section, copying a variable of a class type doesn't duplicate the object; both variables share the same object in memory. This detail explains behaviors that would otherwise seem like strange bugs.
- Tip: always name classes in the singular and in
PascalCase(Book, notBooksorbook): a class describes a single concept, even if you later create many objects from it.
Exercises
-
Define a
Bookclass with the propertiesTitle(string),Author(string),Isbn(string) andAvailable(bool), all of them as auto-implemented properties ({ get; set; }). -
Using the class from the previous exercise, create a
Bookobject calledmyBookassigning its properties one by one (without an object initializer) with the data: title "The Aleph", author "Jorge Luis Borges", ISBN "978-84-376-0497-8" and availabletrue. Print the title and the availability to the console. -
Create two different
Bookobjects using the object initializer (new Book { ... }), with different data for each, and print each one's title followed by its availability to the console, using string interpolation.
Solutions
class Book
{
public string Title { get; set; }
public string Author { get; set; }
public string Isbn { get; set; }
public bool Available { get; set; }
}
Book myBook = new Book();
myBook.Title = "The Aleph";
myBook.Author = "Jorge Luis Borges";
myBook.Isbn = "978-84-376-0497-8";
myBook.Available = true;
Console.WriteLine(myBook.Title);
Console.WriteLine(myBook.Available);
The empty object is created with new Book() and then each property is assigned
separately; at the end, the title ("The Aleph") and the availability (True) are
printed.
Book bookA = new Book { Title = "Ficciones", Author = "Jorge Luis Borges", Isbn = "978-84-376-0496-1", Available = true };
Book bookB = new Book { Title = "Hopscotch", Author = "Julio Cortazar", Isbn = "978-84-376-0495-4", Available = false };
Console.WriteLine($"{bookA.Title} - Available: {bookA.Available}");
Console.WriteLine($"{bookB.Title} - Available: {bookB.Available}");
Each object is created and initialized in a single step thanks to the object initializer; printing them confirms that each one keeps its own values independently.
Conclusion
In this lesson you've taken the most important step of the module: you've learned what a
class is, what an object is, and how to define your first own class, Book, with
auto-implemented properties (Title, Author, Isbn, Available). You now know how to
create objects with new, assign values property by property or through object initializers,
and why classes are reference types. With this, BiblioTechConsola starts leaving behind loose
variables: each book is now a self-contained object.
There's still an important piece missing: for now, a Book object is just a data container,
with no behavior of its own — lending it or printing it still requires code external to the
class. In the next lesson, Methods, you'll learn to add behavior directly to Book (such
as Lend(), Return() or ShowDetails()), so that each object knows how to do things by
itself, not just store data.
C# Programming Course
Module 1: Introduction to C#
- Introduction to C#
- Setting Up the Development Environment
- Hello World Program
- Basic Syntax and Structure
- Variables and Data Types
- Arrays and Strings
Module 2: Control Structures
Module 3: Object-Oriented Programming
- Classes and Objects
- Methods
- Constructors and Destructors
- Inheritance
- Polymorphism
- Encapsulation
- Abstraction
- Structs and Records: Value Types and Reference Types
Module 4: Advanced C# Concepts
- Interfaces
- Delegates and Events
- Pattern Matching and Modern C# Features
- Generics
- Collections
- LINQ (Language Integrated Query)
- Asynchronous Programming
Module 5: Working with Data
- File I/O
- Serialization
- Database Connectivity
- Entity Framework
- Working with JSON and Consuming REST APIs
Module 6: Advanced Topics
- Reflection
- Attributes
- Dynamic Programming
- Memory Management and Garbage Collection
- Multithreading and Parallel Programming
Module 7: Building Applications
Module 8: Best Practices and Design Patterns
- Coding Standards and Best Practices
- Design Patterns
- Dependency Injection and Inversion of Control
- Unit Testing
- Code Review and Refactoring
