Skip to content
wannacode

Your own type

Problem

The prices got mixed up

You are writing the shopping cart of an online store. Every product has a name and a price, so you keep them in two arrays. Index 0 holds the name and price of the first product, index 1 those of the second.

You want the most expensive one first, so you swap the prices:

string[] names = { "Bread", "Milk", "Coffee" };
double[] prices = { 1.20, 2.10, 7.50 };
// Most expensive first: swap the first and the third price.
double temp = prices[0];
prices[0] = prices[2];
prices[2] = temp;
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i] + ": €" + prices[i]);
}
Output
Bread: €7.5
Milk: €2.1
Coffee: €1.2

Bread now costs €7.50. The prices are swapped, but the names are not. The two arrays must always change together, but nothing makes you do it. Add a third array for the quantities, and you have to keep three in mind.

The idea

One product, one place

The name and the price are not separate things. They are parts of one product. We want a "product" type, just like there is int for numbers and string for text.

You make a type like that yourself. It is called a class:

class Product
{
public string Name;
public double Price;
public int Quantity;
}

The variables in the class are its fields. Every product will have its own name, its own price and its own quantity.

The class is only a description: "every product has a name, a price and a quantity". There is no product yet.

public means the fields can be seen from outside too, from Main. Without it, C# does not show them outside. You will see why in the lesson "Encapsulation". In C#, the names of public fields start with a capital letter: Name, Price.

The idea

new: from the description to a product

You create a concrete product from the class with new. It is called an object. You reach its fields with a dot:

Program.cs
class Product
{
public string Name;
public double Price;
public int Quantity;
}
class Program
{
static void Main()
{
Product bread = new Product();
bread.Name = "Bread";
bread.Price = 1.20;
bread.Quantity = 2;
Product coffee = new Product();
coffee.Name = "Coffee";
coffee.Price = 7.50;
coffee.Quantity = 1;
Console.WriteLine(bread.Name + ": €" + bread.Price * bread.Quantity);
Console.WriteLine(coffee.Name + ": €" + coffee.Price * coffee.Quantity);
}
}
Output
Bread: €2.4
Coffee: €7.5
  • The class is outside class Program, above it. A file can have several classes.
  • Product bread is a variable of type Product, just like int count is of type int.
  • new Product() creates a new object. Every object has its own fields: the bread and the coffee do not get in each other's way.
  • bread.Price is "the price of the bread". You read it and write it like an ordinary variable.

Now the name and the price of the product are in one place. Move the product, and they move together.

Try it

Nothing is filled in

If you create a product and fill in nothing, what is in its fields?

What will the program print?

Product item = new Product();
Console.WriteLine(item.Name);
Console.WriteLine(item.Price);
Console.WriteLine(item.Quantity);
Answer

Try it

What is missing?

What goes in the blank so that there is a new product?

Product milk =  Product();
milk.Name = "Milk";
milk.Price = 2.10;

See it

The variable points to the object

You want a sale on coffee, so you make a "copy" to change its price:

Product coffee = new Product();
coffee.Price = 10;
Product sale = coffee;
sale.Price = 8;
Console.WriteLine(coffee.Price); // 8
Step by step, in words
  1. new makes the object, and its fields get starting values. coffee gets an arrow to it.
  2. Follow the arrow from coffee: the price of the object becomes 10.
  3. sale = coffee copies the arrow, not the object. Two arrows, one object.
  4. Follow the arrow from sale: the price in the same object becomes 8.
  5. coffee points to the same object, so it prints 8.

The price of the coffee became 8 too. The reason is that the variable coffee is not the object itself. The object lives separately in memory, and coffee keeps where it is: an arrow to the object. A variable like that is called a reference.

sale = coffee copies the arrow, not the object. Now two arrows point to one object, so the change through sale shows through coffee too.

You saw the same thing in the lesson on arrays: sale = prices gave a second name to the same array. An array is an object too.

The idea

The discount works now

In the "Methods" module, the discount did not work: the method got a copy of the price, changed the copy, and the copy was lost. With an object it is different:

static void Discount(Product p, double percent)
{
p.Price = p.Price * (100 - percent) / 100;
}
Product coffee = new Product();
coffee.Price = 10;
Discount(coffee, 10);
Console.WriteLine(coffee.Price);
Output
9

The parameter is still a copy, but a copy of the arrow. It points to the same object, so the change to p.Price stays after the method too.

More precisely, if you are curious

If the method puts a new object in the parameter, it only moves its own copy of the arrow. The object outside does not change:

static void Reset(Product p)
{
p = new Product();
p.Price = 0;
}
Product coffee = new Product();
coffee.Price = 10;
Reset(coffee);
Console.WriteLine(coffee.Price);
Output
10
That is why people say C# passes by value (except with ref and out), and for objects the value is the reference.

The idea

null: an arrow to nowhere

A variable of a class type may point to nothing. Then it holds null. If you try to read a field through it, there is no object to read it from:

Product gift = null;
Console.WriteLine(gift.Name);

The program compiles, but it stops with an error when it reaches the line:

Error
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.

This is the most common mistake with objects. What an "exception" is and how you catch one, you will see in the module "Errors and exceptions".

Be careful with arrays of objects. new Product[3] makes three places for arrows, not three products. Each one is null until you put new Product() there:

Product[] cart = new Product[3];
Console.WriteLine(cart[0] == null);
cart[0] = new Product();
cart[0].Name = "Bread";
Console.WriteLine(cart[0].Name);
Output
True
Bread

Try it

Find the bug

The program should print "Bread" and "Milk". Instead, it prints "Milk" twice. Which line has the bug?

Pick the line with the bug.

Exercise

Your classes

Solve the tasks in your editor. The class goes above class Program, and you create the objects in Main.

1. Book. A class Book with fields for the title and the author. Create two books and print them.

Output
Under the Yoke by Ivan Vazov
Tobacco by Dimitar Dimov

2. Car. A class SimpleCar with a field for the speed. Create a car (its speed is 0), increase the speed by 10 and print it. In the lesson "Behavior" this will become a method of the car.

Output
Speed after accelerating: 10

3. The cart. The cart from the first card, this time with an array of three Product objects: bread €1.20 (2 pieces), milk €2.10 (1 piece), coffee €7.50 (1 piece). Print the amount for each line and the total. Remember that after new Product[3] there are no products in the array yet.

Output
Bread x2: €2.4
Milk x1: €2.1
Coffee x1: €7.5
Total: €12

4. Most expensive first. Sort the same cart by price, from the most expensive to the cheapest, with the bubble sort from the lesson on arrays. This time you swap whole products, so the name and the price move together.

Output
Coffee: €7.5
Milk: €2.1
Bread: €1.2

More tasks

  • Student. A class Student with a name and three grades (three fields). Create two students and print the average grade of each.
  • One book, two names. Create a book, store it in two variables and change the title through the second one. Print the title through the first one. Explain in words why it works this way.

Test

Check yourself

1. What is the difference between a class and an object?
2. Product sale = coffee; sale.Price = 8; What happens to the price of coffee?
3. What is in the array right after Product[] cart = new Product[3];?
4. A method takes a product as a parameter and changes its price. Can you see the change after the call?
5. Product gift = null; What happens at gift.Name?

Made by Ivo Gergov as part of Evo Tech's campaign for accessible programming education ·