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]);}Bread: €7.5Milk: €2.1Coffee: €1.2Bread 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:
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); }}Bread: €2.4Coffee: €7.5- The class is outside class Program, above it. A file can have several classes.
Product breadis a variable of typeProduct, just likeint countis of typeint.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.Priceis "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);The fields of a new object always have a default value: 0 for numbers, false for booleans and null for text. null means "nothing". Console.WriteLine prints null as an empty line. Local variables in Main have no such value. There the compiler wants you to fill them in before you read them.
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;new: only it creates an object. Without it you only have a variable that does not point to anything yet.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); // 8Step by step, in words
- new makes the object, and its fields get starting values. coffee gets an arrow to it.
- Follow the arrow from coffee: the price of the object becomes 10.
- sale = coffee copies the arrow, not the object. Two arrows, one object.
- Follow the arrow from sale: the price in the same object becomes 8.
- 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);9The 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);10ref 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:
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);TrueBreadTry 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.
Product milk = bread; does not make a new product. Now milk and bread point to the same object, and the name "Milk" replaces "Bread". The fix is Product milk = new Product();.
Exercise
Your classes
1. Book. A class Book with fields for the title and the author. Create two books and print them.
Under the Yoke by Ivan VazovTobacco by Dimitar Dimov2. 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.
Speed after accelerating: 103. 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.
Bread x2: €2.4Milk x1: €2.1Coffee x1: €7.5Total: €124. 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.
Coffee: €7.5Milk: €2.1Bread: €1.2More tasks
- Student. A class
Studentwith 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