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

  1. From loose variables to objects: why classes
  2. What is a class? What is an object?
  3. Defining a class with the class keyword
  4. Fields and properties ({ get; set; })
  5. Creating objects with new
  6. Object initializers
  7. Multiple objects of the same class
  8. Classes versus primitive types: reference types

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

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

  1. Defining a class with the class keyword

A 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 { }:

class Book
{
    // The book's properties will go here
}

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 use camelCase (title, memberNumber). This course will follow this convention strictly from now on.

  1. Fields and properties ({ 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.

class Book
{
    public string title;
    public string author;
}

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, not title), 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 set without 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; }
}

  1. Creating objects with new

Defining 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); // True

Let's break down this key line: Book book1 = new Book();

  • Book (before the variable name) indicates the type of the variable book1: it will be an object of type Book.
  • new Book() creates a new object in memory, following the Book class template, and returns a reference to it.
  • book1 is 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.

  1. 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); // Hopscotch

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

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

  1. 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: writing Book book1; declares a variable capable of referencing a Book, but doesn't create any object; trying to use book1.Title before assigning it new Book() causes a compilation error (or, in certain contexts, a runtime exception if the variable is null).
  • Confusing the class with the object: Book is the template; book1, book2, book3 are concrete objects created from it. It's a common mistake in early lessons to talk about "the class book1" 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, not Books or book): a class describes a single concept, even if you later create many objects from it.

Exercises

  1. Define a Book class with the properties Title (string), Author (string), Isbn (string) and Available (bool), all of them as auto-implemented properties ({ get; set; }).

  2. Using the class from the previous exercise, create a Book object called myBook assigning 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 available true. Print the title and the availability to the console.

  3. Create two different Book objects 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.

© Copyright 2026. All rights reserved