Reader Level:
TUTORIAL

Basics of creating and using classes in C#

Posted by Daniel Clark Tutorials | C# Language May 23, 2011
This chapter is the first of a series that will introduce you to how classes are created and used in C#. It covers the basics of creating and using classes.
  • 2
  • 0
  • 82048
Download Files:
 

This chapter is taken from book " Beginning C# Object-Oriented Programming " by Dan Clark published for Apress.

In the previous chapter, you looked at how the .NET Framework was developed and how programs execute under the framework. That chapter introduced you to the Visual Studio IDE, and you gained some familiarity with working in it. You are now ready to start coding! This chapter is the first of a series that will introduce you to how classes are created and used in C#. It covers the basics of creating and using classes. You will create classes, add attributes and methods, and instantiate object instances of the classes in client code.

After reading this chapter, you should be familiar with the following:

  • How objects used in OOP depend on class definition files.
  • The important role encapsulation plays in OOP.
  • How to define the properties and methods of a class.
  • The purpose of class constructors.
  • How to use instances of classes in client code.
  • The process of overloading class constructors and methods.
  • How to create and test class definition files with Visual Studio.

Introducing Objects and Classes

In OOP, you use objects in your programs to encapsulate the data associated with the entities with which the program is working. For example, a human resources application needs to work with employees. Employees have attributes associated with them that need to be tracked. You may be interested in such things as the employee names, addresses, departments, and so on. Although you track the same attributes for all employees, each employee has unique values for these attributes. In the human resources application, an Employee object obtains and modifies the attributes associated with an employee. In OOP, the attributes of an object are referred to as properties.

Along with the properties of the employees, the human resource application also needs an established set of behaviors exposed by the Employee object. For example, one employee behavior of interest to the human resources department is the ability to request time off. In OOP, objects expose behaviors through methods. The Employee object contains a RequestTimeOff method that encapsulates the implementation code.

The properties and methods of the objects used in OOP are defined through classes. A class is a blueprint that defines the attributes and behaviors of the objects that are created as instances of the class. If you have completed the proper analysis and design of the application, you should be able to refer to the UML design documentation to determine which classes need to be constructed and what properties and methods these classes will contain. The UML class diagram contains the initial information you need to construct the classes of the system.

To demonstrate the construction of a class using C#, you will look at the code for a simple Employee class. The Employee class will have properties and methods that encapsulate and work with employee data as part of a fictitious human resources application.

Defining Classes

Let's walk through the source code needed to create a class definition. The first line of code defines the code block as a class definition using the keyword Class followed by the name of the class. The body of the class definition is enclosed by an open and closing curly bracket. The code block is structured like this:

class Employee
{
}

Creating Class Properties

After defining the starting and ending point of the class code block, the next step is to define the instance variables (often referred to as fields) contained in the class. These variables hold the data that an instance of your class will manipulate. The Private keyword ensures that these instance variables can be manipulated only by the code inside the class. Here are the instance variable definitions:

private int _empID;
private string _loginName;
private string _password;
private string _department;
private string _name;

When a user of the class (client code) needs to query or set the value of these instance variables, public properties are exposed to them. Inside the property block of code are a Get block and a Set block. The Get block returns the value of the private instance variable to the user of the class. This code provides a readable property. The Set block provides a write-enabled property; it passes a value sent in by the client code to the corresponding private instance variable. Here is an example of a property block:

public string Name
{
    get { return _name; }
    set { _name = value; }
}

There may be times when you want to restrict access to a property so that client code can read the property value but not change it. By eliminating the Set block inside the Property block, you create a read-only property. The following code shows how to make the EmployeeID property read-only:

public int EmployeeID
{
    get { return _empID; }
}


Note The private and public keywords affect the scope of the code. For more information about scoping, see Appendix A.

Newcomers to OOP often ask why it's necessary to go through so much work to get and set properties. Couldn't you just create public instance variables that the user could read and write to directly? The answer lies in one of the fundamental tenets of OOP: data encapsulation. Data encapsulation means that the client code does not have direct access to the data. When working with the data, the client code must use clearly defined properties and methods accessed through an instance of the class. The following are some of the benefits of encapsulating the data in this way:

  • Preventing unauthorized access to the data.
  • Ensuring data integrity through error checking.
  • Creating read-only or write-only properties.
  • Isolating users of the class from changes in the implementation code.

For example, you could check to make sure the password is at least six characters long via the following code:

public string Password
{
    get { return _password; }
    set
    {
        if (value.Length >= 6)
        {
            _password = value;
        }
        else
        {
            throw new Exception("Password must be at least 6 characters");
        }
    }
}


Creating Class Methods

Class methods define the behaviors of the class. For example, the following defines a method for the Employee class that verifies employee logins:

public void Login(string loginName, string password)
{
    if (loginName == "Jones" & password == "mj")
    {
        _empID = 1;
        Department = "HR";
        Name = "Mary Jones";
    }
    else if (loginName == "Smith" & password == "js")
    {
        _empID = 2;
        Department = "IS";
        Name = "Jerry Smith";
    }
    else
    {
        throw new Exception("Login incorrect.");
    }
}


When client code calls the Login method of the class, the login name and password are passed into the method (these are called input parameters). The parameters are checked. If they match a current employee, the instance of the class is populated with attributes of the employee. If the login name and password do not match a current employee, an exception is passed back to the client code.

Note Exception handling is an important part of application processing. For more information about exceptions, see Appendix B.

In the previous method, a value is not returned to the client code. This is indicated by the void keyword. Sometimes the method returns a value back to the client calling code (called an output parameter). The following AddEmployee method is another method of the Employee class. It's called when an employee needs to be added to the database, and it returns the newly assigned employee ID to the client. The method also populates the object instance of the Employee class with the attributes of the newly added employee.

public int AddEmployee(string loginName, string password,
string department, string name)
{
    //Data normally saved to database.
    _empID = 3;
    LoginName = loginName;
    Password = password;
    Department = department;
    Name = name;
    return EmployeeID;
}

ACTIVITY 6-1. CREATING THE EMPLOYEE CLASS

In this activity, you will become familiar with the following:

  • Creating a C# class definition file using Visual Studio.
  • Creating and using an instance of the class from client code.

Note If you have not already done so, download the starter files from the source code area of the Apress web site (www.apress.com).

Defining the Employee Class

To create the Employee class, follow these steps:

  1. Start Visual Studio. Select File -> Open -> Project.
     
  2. Navigate to the Activity6_1Starter folder, click the Act6_1.sln file, and click Open. When the project opens, it will contain a login form. You will use this form later to test the Employee class you create.
     
  3. Select Project -> Add Class. In the Add New Item dialog box, rename the class file to Employee.cs, and then click Open. Visual Studio adds the Employee.cs file to the project and adds the following class definition code to the file:

    class Employee
    {
    }
     
  4. Enter the following code between the opening and closing brackets to add the private instance variables to the class body in the definition file:

    private int _empID;
    private string _loginName;
    private string _password;
    private int _securityLevel;
     
  5. Next, add the following public properties to access the private instance variables defined in step 4:

    public int EmployeeID
    {
        get { return _empID; }
    }
    public string LoginName
    {
        get { return _loginName; }
        set { _loginName =value; }
    }
    public string Password
    {
        get { return _password; }
        set { _password =value; }
    }
    public int SecurityLevel
    {
        get { return _securityLevel; }
    }
     
  6. After the properties, add the following Login method to the class definition:

    public void Login(string loginName, string password)
    {
        LoginName = loginName;
        Password = password;
        //Data nomally retrieved from database.
        //Hard coded for demo only.
        if (loginName =="Smith" & password =="js")
        {
            _empID = 1;
            _securityLevel = 2;
     
        }
        else if (loginName == "Jones" & password =="mj")
        {
            _empID = 2;
            _securityLevel = 4;
        }
        else
        {
            throw new Exception("Login incorrect.");
        }
    }
     
  7. Select Build -> Build Solution. Make sure there are no build errors in the Error List window. If there are, fix them, and then rebuild.

Testing the Employee Class

To test the Employee class, follow these steps:

  1. Open frmLogin in the code editor and locate the btnLogin click event code.

    Tip Double-clicking the Login button in the form designer will also bring up the event code in the code editor.\
     
  2. In the body of the btnLogin click event, declare and instantiate a variable of type Employee called oEmployee:

    Employee oEmployee = new Employee();

     
  3. Next, call the Login method of the oEmployee object, passing in the values of the login name and the password from the text boxes on the form:

    oEmployee.Login(txtName.Text,txtPassword.Text);
     
  4. After calling the Login method, show a message box stating the user's security level, which is retrieved by reading the SecurityLevel property of the oEmployee object:

    MessageBox.Show("Your security level is " + oEmployee.SecurityLevel);
     
  5. Select Build -> Build Solution. Make sure there are no build errors in the Error List window. If there are, fix them, and then rebuild.
  6. Select Debug -> Start to run the project. Test the login form by entering a login name of Smith and a password of js. You should get a message indicating a security level of 2. Try entering your name and a password of pass. You should get a message indicating the login failed.
     
  7. After testing the login procedure, close the form; this will stop the debugger.

Using Constructors

In OOP, you use constructors to perform any processing that needs to occur when an object instance of the class becomes instantiated. For example, you could initialize properties of the object instance or establish a database connection. The class constructor method is named the same as the class. When an object instance of a class is instantiated by client code, the constructor method is executed. The following constructor is used in the Employee class to initialize the properties of an object instance of the Employee class. An employee ID is passed in to the constructor to retrieve the values from data storage, like so:

public Employee(int empID)
{
    //Retrieval of data hardcoded for demo
    if (empID == 1)
    {
        _empID = 1;
        LoginName = "Smith";
        Password = "js";
        Department = "IT";
        Name = "Jerry Smith";

    }
    else if (empID == 2)
    {
        _empID = 2;
        LoginName = "Jones";
        Password = "mj";
        Department = "HR";
        Name = "Mary Jones";
    }
    else
    {
        throw new Exception("Invalid EmployeeID");
    }
}


Overloading Methods

The ability to overload methods is a useful feature of OOP languages. You overload methods in a class by defining multiple methods that have the same name but contain different signatures. A method signature is a combination of the name of the method and its parameter type list. If you change the parameter type list, you create a different method signature. For example, the parameter type lists can contain a different number of parameters or different parameter types. The compiler will determine which method to execute by examining the parameter type list passed in by the client.

Note Changing how a parameter is passed (in other words, from byVal to byRef) does not change the method signature. Altering the return type of the method also does not create a unique method signature. For a more detailed discussion of method signatures and passing arguments, refer to Appendix A.

Suppose you want to provide two methods of the Employee class that will allow you to add an employee to the database. The first method assigns a username and password to the employee when the employee is added. The second method adds the employee information but defers the assignment of username and password until later. You can easily accomplish this by overloading the AddEmployee method of the Employee class, as the following code demonstrates:

public int AddEmployee(string loginName, string password,string department, string name)
{
    //Data normally saved to database.
    _empID = 3;
    LoginName = loginName;
    Password = password;
    Department = department;
    Name = name;
    return EmployeeID;
}

public int AddEmployee(string department, string name)
{
    //Data normally saved to database.
    _empID = 3;
    Department = department;
    Name = name;
    return EmployeeID;
}


Because the parameter type list of the first method (string, string) differs from the parameter type list of the second method (string, string, string, string), the compiler can determine which method to invoke. A common technique in OOP is to overload the constructor of the class. For example, when an instance of the Employee class is created, one constructor could be used for new employees and another could be used for current employees by passing in the employee ID when the class instance is instantiated by the client. The following code shows the overloading of a class constructor:

public Employee()
{
    _empID = -1;
}

public Employee(int empID)
{
    //Retrieval of data hard coded for demo
    if (empID == 1)
    {
        _empID = 1;
        LoginName = "Smith";
        Password = "js";
        Department = "IT";
        Name = "Jerry Smith";

    }
    else if (empID == 2)
    {
        _empID = 2;
        LoginName = "Jones";
        Password = "mj";
        Department = "HR";
        Name = "Mary Jones";
    }
    else
    {
        throw new Exception("Invalid EmployeeID");
    }
}


ACTIVITY 6-2. CREATING CONSTRUCTORS AND OVERLOADING METHODS

In this activity, you will become familiar with the following:

  • Creating and overloading the class constructor method.
  • Using overloaded constructors of a class from client code.
  • Overloading a method of a class.
  • Using overloaded methods of a class from client code.

Creating and Overloading Class Constructors

To create and overload class constructors, follow these steps:

  1. Start Visual Studio. Select File --> Open --> Project.
     
  2. Navigate to the Activity6_2Starter folder, click the Act6_2.sln file, and then click Open. When the project opens, it will contain a frmEmployeeInfo form that you will use to test the Employee class. The project also includes the Employee.cs file, which contains the Employee class definition code.
     
  3. Open Employee.cs in the code editor and examine the code. The class contains several properties pertaining to employees that need to be maintained.
     
  4. After the property declaration code, add the following private method to the class. This method simulates the generation of a new employee ID.

    private int GetNextID()
    {
        //simulates the retrieval of next
        //available id from database
        return 100;
    }
     
  5. Create a default class constructor, and add code that calls the GetNextID method and assigns the return value to the private instance variable _empID:

    public Employee()
    {
    _empID = GetNextID();
    }
     
  6. Overload the default constructor method by adding a second constructor method that takes an integer parameter of empID, like so:

    public Employee(int empID)
    {
    //Constructor for existing employee
    }
     
  7. Add the following code to the overloaded constructor, which simulates extracting the employee data from a database and assigns the data to the instance properties of the class:

    //Simulates retrieval from database
    if (empID == 1)
    {
        _empID = empID;
        LoginName ="smith";
        PassWord = "js";
        SSN = 123456789;
        Department = "IS";
    }
    else if (empID == 2)
    {
        _empID = empID;
        LoginName ="jones";
        PassWord = "mj";
        SSN = 987654321;
        Department = "HR";
    }
    else
    {
        throw new Exception("Invalid Employee ID");
    }
     
  8. Select Build -> Build Solution. Make sure there are no build errors in the Error List window. If there are, fix them, and then rebuild.

Testing the Employee Class Constructors

To test the Employee class constructors, follow these steps:

  1. Open the EmployeeInfoForm in the form editor and double click the New Employee button to bring up the click event code in the code editor.
     
  2. In the Click Event method body, declare and instantiate a variable of type Employee called oEmployee:

    Employee oEmployee = new Employee();

     
  3. Next, update the EmployeeID text box with the employee ID, disable the EmployeeID text box, and clear the remaining textboxes:

    Employee oEmployee = new Employee()
    txtEmpID.Text = oEmployee.EmpID.ToString();
    txtEmpID.Enabled = false;
    txtLoginName.Text = "";
    txtPassword.Text = "";
    txtSSN.Text = "";
    txtDepartment.Text = "";

     
  4. Select Build -> Build Solution. Make sure there are no build errors in the Error List window. If there are, fix them, and then rebuild.
     
  5. Open the EmployeeInfoForm in the form editor and double click the Existing Employee button to bring up the click event code in the code editor.
     
  6. In the Click Event method body, declare and instantiate a variable of type Employee called oEmployee. Retrieve the employee ID from the txtEmpID text box and pass it as an argument in the constructor. The int.Parse method converts the text to an integer data type:

    Employee oEmployee = new Employee(int.Parse(txtEmpID.Text));

     
  7. Next, disable the Employee ID textbox and fill in the remaining text boxes with the values of the Employee object's properties:

    txtEmpID.Enabled =false;
    txtLoginName.Text = oEmployee.LoginName;
    txtPassword.Text = oEmployee.PassWord;
    txtSSN.Text = oEmployee.SSN.ToString();
    txtDepartment.Text = oEmployee.Department;
     
  8. Select Build -> Build Solution. Make sure there are no build errors in the Error List window. If there are, fix them, and then rebuild.
     
  9. Select Debug -> Start to run the project and test the code.
     
  10. When the EmployeeInfo form is displayed, click the New Employee button. You should see that a new employee ID has been generated in the Employee ID textbox.
     
  11. Click the Reset button to clear and enable the Employee ID text box.
     
  12. Enter a value of 1 for the employee ID and click the Get Existing Employee button. The information for the employee is displayed on the form.
     
  13. After testing the constructors, close the form, which will stop the debugger.

Overloading a Class Method

To overload a class method, follow these steps:

  1. Open the Employee.cs code in the code editor.
     
  2. Add the following Update method to the Employee class. This method simulates the updating of the employee security information to a database:

    public string Update(string loginName, string password)
    {
        LoginName = loginName;
        PassWord = password;
        return "Security info updated.";
    }

     
  3. Add a second Update method to simulate the updating of the employee human resources data to a database:

    public string Update(int ssNumber, string department)
    {
        SSN = ssNumber;
        Department = department;
        return "HR info updated.";
    }

     
  4. Select Build -> Build Solution. Make sure there are no build errors in the Error List window. If there are, fix them, and then rebuild.

Testing the Overloaded Update Method

To test the overloaded Update method, follow these steps:

  1. Open the EmployeeInfo Form in the Form editor and double click the Update SI button. You are presented with the click event code in the Code Editor window.
     
  2. In the Click Event method, declare and instantiate a variable of type Employee called oEmployee. Retrieve the employee ID from the txtEmpID text box and pass it as an argument in the constructor:

    Employee oEmployee = new Employee(int.Parse(txtEmpID.Text));

     
  3. Next, call the Update method, passing the values of the login name and password from the text boxes. Show the method return message to the user in a message box:

    MessageBox.Show(oEmployee.Update(txtLoginName.Text, txtPassword.Text));

     
  4. Update the login name and password text boxes with the property values of the Employee object:

    txtLoginName.Text = oEmployee.LoginName;
    txtPassword.Text = oEmployee.PassWord;
     
  5. Repeat this process to add similar code to the Update HR button Click Event method to simulate updating the human resources information.

    Add the following code to the Click Event method:

    Employee oEmployee = new Employee(int.Parse(txtEmpID.Text));
    MessageBox.Show(oEmployee.Update(int.Parse(txtSSN.Text), txtDepartment.Text));
    txtSSN.Text = oEmployee.SSN.ToString();
    txtDepartment.Text = oEmployee.Department;
     
  6. Select Build -> Build Solution. Make sure there are no build errors in the Error List window. If there are, fix them, and then rebuild.
     
  7. Select Debug -> Start to run the project and test the code.
     
  8. Enter a value of 1 for the employee ID and click the Get Existing Employee button.
     
  9. Change the values for the security information and click the Update button.
     
  10. Change the values for the human resources information and click the Update button.
     
  11. You should see that the correct Update method is called in accordance with the parameters passed in to it. After testing the Update method, close the form.

Summary

This chapter gave you a firm foundation in creating and using classes in C# code. Now that you are comfortable constructing and using classes, you are ready to look at implementing some of the more advanced features of OOP. In the next chapter, you will concentrate on how inheritance and polymorphism are implemented in C# code. As an object-oriented programmer, it is important for you to become familiar with these concepts and learn how to implement them in your programs.

COMMENT USING

Trending up