Lesson # 17. C# Classes

Programming on c sharp in Microsoft Visual Studio. C# Classes

Содержание:

Theory

Lecture in pdf format

  • C# classes encapsulate data and associated functionality into an object;
  • Encapsulation encloses data and functionality into a single unit (called a class);
  • data and functionality are separated into two separate protections public and private:
  • Public members can be accessed by client code.
  • Private members cannot be accessed by client code (only used within the class itself)
  • The objects of a class have three things:
    First, objects have state. It’s the current characteristics of that object and those characteristics might and probably will change within the program. The second thing, all objects have is behavior. Finally, all objects have identity. If our system is a bunch of interacting objects, then we have to be able to tell them apart. And so, each object has their own identity. And it turns out that in practice, the identity of the object is the memory address of that object.
  • state of an object is stored in fields in C-sharp;
  • behavior in C-sharp is implemented in a method.
Class definition
  • private modifier – is the default modifier for members

  • Class definition sample:

    public class Person
    {
    	private string Name; // state or field
    	private int Age;
     
    	public Person(string Name, int Age) // constructor
    	{
               // to initialize class fields is the main role of a constructor
    		this.Name = Name; 
    		this.Age = Age;
    	}
    	public void Print() // behavior or method
    	{
    		Console.WriteLine($"{Name} {Age}");
    	}
    }
  • When an instance of a class is created, the class constructor sets up the initial state of the class.
  • The simplest constructor we can provide is a custom default constructor that specifies the state of the object when the object is constructed.
  • Working with class within the Main function:

    class Program
    {
    	static void Main(string[] args)
    	{
              // how to create an instance of the class?
              // 1 way:
    		Person p1 = null;
    		p1 = new Person("Name1", 20); // an instance of the class
              // 2 way:
    		Person p2 = new Person("Name2", 21);
              // 3 way:
    		var p3 = new Person("Name3", 19);
              // to print out:
    		p1.Print(); p2.Print(); p3.Print();
    	}
    }
  • Properties allow to restrict access to the fields:
How to copy and compare objects
  • Variable of a class type is a reference to an object
  • public class Person
    {
    	...
    	public Person(string Name, int Age)
    	{
    		this.Name = Name;
    		this.Age = Age;
    	}
    }
    Person p;
    p = new Person("Name",18);
     
    var p1 = p; // Assignment of references
     
    if (p1==p) ... // Comparison of references
     
    p = null; // Garbage collection
    void Print(Person p) {}

Labs and Tasks

Lab 0:
To do: Create a Rectangle class and an object (i.e., a variable) of this class, called rect.
1) The class should contain four members:
— two data members of type int (fields: Width and Height) with private access,
— and two member functions (methods) with public access: the functions setValues and getArea.

2) Define two member functions (methods): setValues method should set the variables Width and Height to the values; area function should return width*height.

3) Create a constructor to have the initial values for Width and Height (set them to 5).

4) Set the Width and Height values for the rect object and print out the information about this object.

Expected output:

Lab 0:
please, enter width:
>> 20
please, enter height:
>> 2
rect area: 40

✍ Algorithm:

  • To do the lab create empty console application with a name Lesson9
  • 1. Create a Rectangle class:

  • Add Rectangle.css class-file into the project. Open the file and add the code to define the class with two private data members (fields), they are Width and Height.
  • internal class Rectangle
        {
            private int Width;
            private int Height;
        }
    
  • Here Rectangle is the class name (i.e., the type).
  • Width and Height members cannot be accessed from outside the class, since they have private access and they can only be referred to from within other members of that same class.
  • 2. Define two member functions:

  • Now, define two member methods with public access, they are setValues and getArea.
  • Since members Width and Height have private access, access to them from outside the class is not allowed. So, we should define a member function to set values for those members within the object: the member function setValues. Add the code just after created fields Width and Height:
  • public void setValues(int width, int height)
            {
                this.Width = width;
                this.Height = height;
            }
    
  • The function setValues has access to the variables Width and Height, which are private members of class Rectangle, and thus only accessible from other members of the class, such as this.
  • The functions setValues and getArea have a public access, it means that they can be accessed from inside the main function by simply inserting a dot (.) between object name and member name (e.g. rect.setValues…).
  • The second member function, that is GetArea function. Add the definition inside the class after the definition of setValies method:
  • public int getArea()
            {
                return Width* Height;
            } 
    

    3) Create a constructor to have the initial values for Width and Height (set them to 5).

  • Add the declaration of a constructor inside the class scope after the functions:
  • public Rectangle()
            {
                this.Width = 5;
                this.Height = 5;
            }
    
  • Open main file code and define the instance of the new class object (i.e., a variable). Declare another variable to store the result after a call of getArea function. Output the variable value.
  • static void Main(string[] args)
            {
                Rectangle rect = new Rectangle();
                var area = rect.getArea();
                Console.WriteLine(area);
            }
    

    4) Set the width and height values for the rect object and print out the information about this object:

  • After this, ask user to input new width and height values. Call the setValues function. Then call the getArea function once again to have area being calculated for new values:
  •             int w = int.Parse(Console.ReadLine());
                int h = int.Parse(Console.ReadLine());
                rect.setValues(w, h);
                area = rect.getArea();
                Console.WriteLine(area);
    
  • Run the program and check the output.

Task 0:

To do: Create a Cube class.
1) The class should contain four members:
Length data member of type double with private access,
— three member functions/methods with public access: the functions double getVolume(), double getSurfaceArea() and void Print().

2) Give the definitions (implementations) of those functions:
getVolume() method has to calculate a volume of the cube: Length * Length * Length;
getSurfaceArea() method has to calculate a Surface Area of the cube: 6 * Length * Length;.
Print() method has to display the information of the cube (it’s length).

3) Create a constructor to have the initial value for Length field (set it to 1).

4) Create read- and write- property (setter and getter) for the Length field. Before setting the value, check if it is not less than 1. If it is, so throw the exception about it. How to throw the exception:

//including namespace to throw the exceptions:
using System.Diagnostics;
...
// inside the setter code:
if (...)
   throw new System.ArgumentException("The length is not correct");

5) Inside the main function create an instance of cube class, that is an object, of length 10. Print out the information about this object (length, volume, area).

Expected output:

Task 0:
The length: 10
Volume of cube:
1000
Surfac eArea of cube:
600

Lab 1.

Perform tasks in the Main function with a comment on which item of the task is being performed.

To do:
1. Create the Cow class with two fields: name and weight.
2. Provide class constructor with two parameters, they are a non-empty name and a positive weight; and also the Print/Println method. Don’t forget to check whether the field values are correct.
3. Within the Main program initialize two instances of the Cow class object, call the Println method for them.
4. Add the read and write properties for all fields to the Cow class. Don’t forget to check the correctness of weight and name values (check in the Main program).
5. Create two external procedures or methods (TestCowValue and TestCowVar) with a single parameter of Cow type. Within the first one the parameter by value must be provided, and within the second the parameter by reference must be provided.

  • Assign a new object to the parameter inside the procedures (any object, since the constructor must be called).
  • Inside the Main program, create an object of the Cow class and call the Println method for the created object.
  •   
    6. Create an array of objects of the Cow class with four elements inside it. Initialize the elements with values. Create a method to print the array out.
    7. Create a static attribute to store the information about total number of the cows.

    The resulting example:

    Name: Lovely
    Weight: 56
    Name: Bunny
    Weight: 90
    cow3 before reassigning:
    Name: Lucy Weight: 500
    cow3 after reassigning a property by the value :
    Name: Lucy Weight: 500
    cow4 before reassigning:
    Name: Laserda Weight: 400
    cow4 after reassigning a property by the reference:
    Name: Stark Weight: 325
    The array:
    Name: Lassie Weight: 200 Name: Bern Weight: 325 Name: Emerald Weight: 333 Name: Sindy Weight: 256
    Total number of cows: 8
    

    [Solution and Project name: Lesson_17Lab1, file name CowsClass.cs]

    ✍ How to do:

    • Create a new project with the name and file name as it is specified in the task.
    • Include all the namespaces and classes that we’ll need for our project. In order not to type always Diagnostics namespace, that is used for debugging process, and the Console class, we’ll include them in our project. Enter the code in the including section at the top of the screen:
    • using System.Diagnostics;
      using static System.Console;
      

      1. Create a Cow class with two fields: name and weight.

       class Cow
              {
                  private string name;
                  private double weight;
               // ... class constructor must be here
              } // end of class Cow
      

      2. Create a class constructor with two parameters, they are a non-empty name and a positive weight; and also the Print/Println method. Don’t forget to check whether the field values are correct.

    • The class constructor has to be of Public access modifier:
    • public Cow(string name, double weight)  // constructor
          {
               ...
           }// end of constructor
      
    • To check whether the field name is empty, you need to use an ArgumentException class, to throw an exception error in the case if the name is empty. Place the code inside the constructor:
    •  if (name=="")
                throw new System.ArgumentException("The name can't be empty");
      
    • Check the value of the weight field in the same way:
    •  if (weight <= 0)
                throw new System.ArgumentOutOfRangeException("The weight must be > 0");
      
    • Class constructor has to specify the state of the object when the object is constructed. So you need to set up the initial state of the class fields. Add the following code into the constructor after if statements:
    •  this.name = name;
       this.weight = weight;
      
    • Create a print method to print out the fields values within a single line. Use a short syntax. Create printLn method to print them out within two lines. Use a usual syntax. Add the code to the class Cow :
    • public void Print() => Write($"Name: {name} Weight: {weight} ");
      public void Println()
                  {
                      WriteLine($"Name: {name}");
                      WriteLine($"Weight: {weight}");
                  }
      // don't type the curly brace, you already have it:
      }// end of class Cow
      

      3. Within the Main program initialize two instances of the Cow class object, call the Println method for them.

      var cow1 = new Cow("Lovely", 56);
      var cow2 = new Cow("Bunny", 87);
      cow1.Println();
      cow2.Println();
      
    • Run the application and check the output.
    • The new keyword will arrange for us that when the function constructor creates an empty object and then sets it to be a cow, it will go ahead and return that object and store it in whatever variable that we’re providing for it. We’ve provided cow1 and cow2, they are the instances of the cow object.
    • But if we try to print out the name of cow1, using WriteLine(cow1.name); statements, we’ll have an error («name is inaccessible due to its protection level»). So, we need to create public properties for the fields of our Cow class.
    • 4. Add the read and write fields to the Cow class. Don’t forget to check the correct weight and name values.

    • First, let’s create a read and write property for the name field. Use get keyword to return the field value and set keyword — to assign a new value to it:
    • public string Name
              {
                  get { return name; }
                  set
                  {
                      if (value.Length > 0)
                          name = value;
                      else
                          throw new System.ArgumentException("The name can't be empty");
                  }
              }// end of property Name
      
    • A similar code has to be created for the weight field:
    • public double Weight
                  {
                      get { return weight; }
                      set
                      {
                          if (weight > 0)
                              weight = value;
                          else
                              throw new System.ArgumentOutOfRangeException("The weight has to be > 0");
                      }
                  }// end of property Weight
      
    • Go back to the Main function and assign a new value for cow2 weight before printing the results. Run the application and check the result: the name of cow2 has to be set to the new one:
    • cow2.Weight = 90;
      cow2.Println(); // you already have this
      

      5. Create two external procedures or methods (TestCowValue and TestCowVar) with a single parameter of Cow type. Within the first method the parameter by value must be provided, and within the second the parameter by reference must be provided.

    • First, let’s create a method TestCowValue that takes one parameter by the value:
    •  static void TestCowValue(Cow myCow)
              {
                  myCow = new Cow("Star", 325);
              }
      
    • Within the Main function initialize a new instance of the Cow class and print out the values of its fields. Call the created method for it and print the fields again:
    •  // Task 5
       Cow cow3 = new Cow("Lucy", 500);
       WriteLine("Before reassigning:");
       cow3.Print();
       WriteLine();
       WriteLine("After reassigning a property by the value :");
       TestCowValue(cow3); //can't change the value
       cow3.Print();
      
    • Run the application and check the output.
    • The values of the fields were not changed, because the TestCowValue method didn’t return new values — it takes the parameter by value.
    • Let’s create the TestCowVar method that takes a parameter by reference:
    • static void TestCowVar(ref Cow myCow)// parameter by ref
              {
                  myCow = new Cow("Star", 325);
              }
      
    • Within the Main function initialize a new instance of the Cow class and print out the values of its fields. Call the created method for it and print the fields again:
    • WriteLine();
      WriteLine("cow4 before reassigning:");
      Cow cow4 = new Cow("Laserda", 400);
      cow4.Print();
      WriteLine();
      WriteLine("cow4 after reassigning a property by the reference:");
      TestCowVar(ref cow4);
      cow4.Print();
      ReadKey();
      

      6. Create an array of objects of the Cow class with four elements inside it. Initialize the elements with values. Create a method to print the array out.

    • Within the Main function initialize the single-dimentional array of the Cow class:
    • // Task 6
      Cow[] cows = new Cow[] {
      	new Cow("Lassie", 200),
      	new Cow("Bern", 325),
      	new Cow("Emerald", 333),
      	new Cow("Sindy", 256)
      };
      
    • Create a PrintCows method to print out the elements of the array. You should do it within the class Program:
    • public static void PrintCows(Cow[] cows)
      	{
      		foreach (Cow cow in cows)
      		{
      			cow.Print();
      		}
      	} // end of the PrintCows method
      
    • Return to the Main function and call the method:
    • WriteLine("The array:");
      PrintCows(cows);
      

      7. Create a static attribute to store the information about total number of the cows.

    • Now, let’s add the static attribute of the class to have possibility to print out the information about total number of cows. Return to the class code and insert there:
    • public static int Number = 0;
      
      You should initialize it with 0, because the compiler will start count from 0.
      Static attribute means the attribute for the class itself, not for the objects of the class.
    • To count the cows you should place the increment of the attribute into the constructor of the class. Therefore, whenever an object is created, the number of cows will be increased.
    • //...
      Number++;
      
    • Output the number inside Main method:
    • Console.WriteLine(Cow.Number);
      
    • Run the application again and check the output.
    • Save and upload the file into the moodle system.

    Task 1:

    Perform tasks in the Main program file with a comment on which item of the task is being performed.

    To do:
    1. Create the TransportCompany class with three fields: for the company name, for the planned number of product containers sent, and for the actual number of product containers sent.
    2. Create auto read- and write- properties for all the fields.
    3. Define a constructor with the fields, and add the Print/Println methods for the class.
    4. Within the Main function initialize two instances of the class. Print out the information about them.
    5. Create a PlanIsDone method (returns true if the plan is done, that is the number of sent containers grater or equal to the number of planned contaiers). The method has one parameter — the instance of the created class object. Call the method for one of the companies within the Main function.
    6. Create and fill in a dynamic array of objects with data about several companies: the company name, the number of containers planned to be sent and the number of containers actually sent.
    7. Output all elements of the array (create a new method to do it).
    * extra task 8. Create a function that returns an array of companies’ names that completed the plan. Print the names using a another method.

    Note: Specify the meaningful names for the class, its fields, and methods / functions.

    The resulting example:

    Company name: BMW. Was sent: 2, Was planned: 3
    Company name: Lada. Was sent: 4, Was planned: 3
    The plan for the BMW company was done: False
    # 7:
    The companies:
    Company name: Mazda. Was sent: 25, Was planned: 20
    Company name: Opel. Was sent: 30, Was planned: 32
    Company name: Honda. Was sent: 33, Was planned: 33
    Company name: Nissan. Was sent: 20, Was planned: 25
    # 8:
    Successful companies:
    Company name: Mazda. Was sent: 25, Was planned: 20
    Company name: Honda. Was sent: 33, Was planned: 33
    

    [Solution and Project name: Lesson_17Task1, file name L17Task1.cs]


    Task 2:

    Perform tasks in the Main program file with a comment on which item of the task is being performed.

    To do:
    1. Create a Student class with four fields: name, course number, group number, and number of classes of absence.
    2. Define a constructor with the fields, and add the Print/Println methods for the class. Add auto read and write properties for all fields.
    3. Fill in an array of students.
    4. Create a method to print out the names of students from the array who belong to a particular course and group, and missed more than N classes.

    Note: Specify the meaningful names for the class, its fields, and methods / functions.

    The resulting example:

    The array of students: 
    Ivanov, course 2, group 23, was absent 2 classes
    Petrov, course 1, group 9, was absent 5 classes
    Sidorova, course 2, group 23, was absent 0 classes
    Ivanov, course 2, group 23, was absent 2 classes
    
    Enter the course number, group number and missed classes:
    1  9  3
    Petrov
    

    [Solution and Project name: Lesson_17Task2, file name L17Task2.cs]


    Task 3: Static attribute

    To do: Create a BookShop class to store and output an information about the selling books.

    1) The class should contain the following members:
    data members with private access:
    Title (a title of a book) of type string;
    Author (an author of a book) of type string;
    Price (a price of a book) of type double;
    Discount (a discount for a price of a book) of type int.

    data member with public access:
    double GetTotalPrice() method to calculate the price of a book considering the discount (price — (price * discount)).

    2) Create a constructor with four arguments to have the initial values for books.

    3) Create the properties for all the fields (so, create getters and setters).

    4) Create static attribute Number to store a total number of the books. Initialize it with 0. Insert the increasing of the number into the constructor (Number++). And output total number of the books.

    5) Create two objects and print out the information about those objects. Print out the info about the price considering the discount.

    Expected output:

    Task 3:
    // book 1 info:
    Dostoevsky Demons 205 roubles, discount 0.05, total price 194,75 roubles
    // book 2 info:
    Kuprin Duel 125 roubles, discount 0.1, total price 112,5 roubles
    Tota number of the books is 2
    

    [Solution and Project name: Lesson_17Task3, file name L17Task3.cs]


    Extra task

    ExTask 1:

    Perform tasks in the Main program.

    To do:
    Add a code to create text files with names day1.txt, day2.txt, day3.txt. Each file have to contain the surnames of students who walked around the university without masks on day No.1, No.2 and No.3 (in each line of the file). Find students who violated the regime on all days, and prepare a list for expulsion.

    Note: The class of stunets must be created. Specify the meaningful names for the class, its field(s) and methods. Add method to print out information from the files. Create a string method of the class to print out the surnames of those students who are expelled.

    The resulting example:

    The array of students from day1: 
    Ivanov Petrov Sidorov Musina
    The array of students from day2: 
    Koslov Petrov Legkov
    The array of students from day3: 
    Petrov Kuzmin Antonov
    Expelled students:
    Petrov
    

    [Solution and Project name: Lesson_17ExTask1, file name L17ExTask1.cs]