Chapter 3
Learning Just Enough C# and VB.NET: Types and Members

Key Skills & Concepts

Image Create Classes

Image Write Methods

Image Code Fields and Properties

A type is a general term for classes, modules, enums, and more. This chapter will specifically discuss the class type, which allows you to create your own custom types. You’ll also see the value of a class when you learn about class members. You’ll see how the field, method, and property class members can be used. We’ll start with learning how to create and use classes.

Creating Classes

Previously, you learned about the primitive types, which are built into languages and alias the underlying .NET types. You can also create your own types, via classes, which you can instantiate and create objects with. The following section explains how to create a class and then instantiate an object from it.

Class Syntax

To create a new custom class definition, right-click the project, select Add | Class, name the class Employee for this example, and type the file extension .cs for C# or .vb for VB; then click Add (VS will add this file extension for you if you don’t). You’ll see a file with the same code as Listing 3-1.

Listing 3-1 A new Employee class

C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram

{
    public class Employee
    {
       public string FirstName;
    }
}

VB:

Public Class Employee
  Public Dim FirstName As String
End Class

The C# Employee class is nearly the same as the Program class that you created in the preceding chapter, except that the class name here is Employee. In VB, you’ve only created a module before, and the Employee class is your first class for this book. You can add members to a class, which could be events, fields, methods, and properties. Listing 3-1 shows an example of a field, FirstName, and you’ll learn about events, methods, and properties in later sections of this chapter. A field is a variable in a class that holds information specific to that class.

Listing 3-2 shows how to instantiate an object of type Employee, which is your new custom type, and use it. You would put this code inside of Main or another method. You’ll learn more about methods in the later section “Writing Methods.”

Listing 3-2 Code that uses a class

C#:

Employee emp = new Employee();
emp.FirstName = "Joe";

VB:

Dim emp As New Employee
emp.FirstName = "Joe"

In Listing 3-2, you can see that emp is a variable declared as type Employee. The C# new Employee() or VB New Employee clause creates a new instance of Employee, and you can see that this new instance is being assigned to emp. With that new instance, via the emp variable, you can access the Employee object, including its instance members. In Listing 3-2, the FirstName field of that particular instance of Employee is assigned a string value of “Joe”. Here you see that an object can contain data.

Now that you can define a new class, create an instance from that class, and use it, the next section shows you another feature of classes called inheritance.

Class Inheritance

One class can reuse the members of another through a feature known as inheritance. In programming terms, we say a child class can derive from a parent class and that child class will inherit members (such as fields and methods) of the parent class that the parent class allows to be inherited. The following example will create a Cashier class that derives from the Employee class. To create this class, right-click the project, select Add | Class, and name the class Cashier. Listing 3-3 shows the new class and modifications for implementing inheritance.

Listing 3-3 Class inheritance

C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram
{
    public class Cashier  : Employee
    {
    }
}

VB:

Public Class Cashier
   Inherits Employee

End Class

The C# inheritance relationship is indicated by the colon after the Cashier identifier, followed by the class being derived from, Employee. In VB, you write the keyword Inherits, on a new line, followed by the class being derived from. Essentially, this means that Cashier has all of the same members as Employee. Listing 3-4 demonstrates the benefits of inheritance.

Listing 3-4 Code using inheritance

C#:

Cashier cashr = new Cashier();
cashr.FirstName = "May";

VB:

Dim cashr As New Cashier
cashr.FirstName = "May"

According to Listing 3-4, Cashier does not have a field named FirstName. However, Employee does have a FirstName field and Cashier derives from Employee. Because of inheritance, Cashier automatically inherits FirstName, and the code in Listing 3-4 is perfectly legal. Inheritance can be thought of as specialization in the sense that, in this example, Cashier is a specialized kind of Employee. To take advantage of this specialization, you could add a new field to your new Cashier class called “assignedCashRegister” where now, not only does the Cashier class have the fields and methods of Employee, it is able to hold the value for a specific cash register name or number. An instance of the Employee class would not be able to contain this information. The .NET Framework uses inheritance extensively to offer you reusable class libraries.

TIP

You can often use the phrase “is a” to describe the relationship between inherited classes when starting from the child class. For example, you can say “Cashier is an Employee.” If you apply this phrase technique to your software design and the sentence sounds logically correct, then you’ve probably used inheritance correctly.

The class Snippet

C# has a class snippet, but VB doesn’t. Before using the class snippet, create a new class file by right-clicking the project, select Add | New Item | Code File, and name the file Manager. You’ll now have a blank file to work with. To use the class snippet, type cl and press TAB, TAB; and you’ll see the snippet template in Figure 3-1.

Image

Figure 3-1 The C# class snippet template

Just type in the class name in the field and press ENTER. The carat will locate to the inside of the class block. Now that you know how to create classes, you’ll need to know how to add members, starting with methods.

Writing Methods

You can divide your algorithms into blocks of code called methods. In different programming languages, methods are called functions, procedures, or subroutines. I’ll use the term method as a generic term, except when I need to be more specific. You’ve already used methods when coding Console.WriteLine, where WriteLine is a method of the Console class. A method contains one or more statements. Reasons for creating methods include the ability to modularize your code, isolate complex operations in one place, or group a common operation that can be reused in multiple places. The following sections show you how to declare and use methods.

Declaring and Using a Method

To start off, I’ll show you a very simple method so that you can see the syntax and understand the program flow. Listing 3-5 will move the Console.Writeline statement from the Main method discussed in Chapter 2 into a new containing method and then add a statement to the Main method that calls the new method.

Listing 3-5 Declaring and calling a method

C# (Program.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            MessagePrinter msgPrint = new MessagePrinter();
            msgPrint.PrintMessageInstance();
        }
    }

C#: (MessagePrinter.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram
{
    class MessagePrinter
    {
        public static void PrintMessageStatic()
        {
             Console.WriteLine("Hello from a static method.");
        }

        public void PrintMessageInstance()
        {
             Console.WriteLine("Hello from an instance method.");
        }
    }
}

VB (Module1.vb):

Module Module1
   Sub Main()
       MessagePrinter.PrintMessageShared()

       Dim msgPrint As New MessagePrinter()
       msgPrinter.PrintMessageInstance()
   End Sub
End Module

VB (MessagePrinter.vb)

Public Class MessagePrinter
    Public Shared Sub PrintMessageShared()
        Console.WriteLine("Hello from a shared method.")
    End Sub

    Public Sub PrintMessageInstance()
        Console.WriteLine("Hello from an instance method.")
    End Sub
End Class

Listing 3-5 has two types of methods, static and instance. In VB, shared methods are the same as static. You can tell which type of method each is because static methods have the static modifier (shared in VB), but instance methods don’t have a static (or shared in VB) modifier. First, let’s look at the static (shared) method declaration, and then you’ll see how it’s called.

The static (shared in VB) method, PrintMessageStatic (PrintMessageShared in VB) has a public access modifier, which means that any other code using the containing class, MessagePrinter, will be able to see the method. If you didn’t include the public access modifier, the method would automatically default to being private and only other code residing within the MessagePrinter class would be able to use that method.

PrintMessageStatic has a void keyword, meaning that this method does not return a value. In VB, you indicate that a method does not return a value by making it a Sub, as was done in Listing 3-5. Later, you’ll learn how to create a method that does return values to its calling code that invokes this method. The empty parameter list appended to the PrintMessageStatic (PrintMessageShared in VB) means that there are not any parameters for this method. Parameters allow callers to pass information to the method; a subject we’ll discuss soon.

Within the method block, you can see that there is a Console.WriteLine statement. You can add as many statements as you need for the purpose of the method. Next, we’ll examine how PrintMessageStatic (PrintMessageShared in VB) is called, which the following code repeats from Listing 3-5:

C#:

Program.PrintMessageStatic();

VB:

MessagePrinter.PrintMessageShared()

Viewing the preceding example, which shows a statement inside of the Main method, you can see the call to Program.PrintMessageStatic (PrintMessageShared in VB). Notice that the class (aka type) that contains all the methods is named MessagePrinter. In C#, a static method is called through its containing type, which is why you call PrintMessageStatic with the Program prefix. In VB, you can invoke shared methods through either the method’s type or an instance of that type. We discuss instance methods next.

The next method, PrintMessageInstance, is an instance method; it has no static modifier. The rest of the method definition mirrors that of the PrintMessageStatic method. Since PrintMethodInstance is an instance method, you call it differently; through an instance of its containing type, which the following code repeats from Listing 3-5:

C#:

MessagePrinter msgPrint = new MessagePrinter();
msgPrint.PrintMessageInstance();

VB:

Dim msgPrint As New MessagePrinter()
msgPrinter.PrintMessageInstance()

As this example shows, the type of msgPrint is MessagePrinter. Using the statement new MessagePrinter creates a new instance of MessagePrinter at runtime, which is assigned to the msgPrint variable. Now that you’ve created an instance of a MessagePrinter and msgPrint has a reference to that instance, you can call the instance method, PrintMessageInstance, via the msgPrint variable. Next, let’s look at how to add parameters to a method and discuss why that’s important.

Declaring Parameters and Passing Arguments

Passing parameters to a method is a great way to make code more reusable. For example, what if you had a method that printed a report containing the names of all customers? It wouldn’t make sense to create one method for each customer, especially when the list changes all the time. Listing 3-6 shows a method that takes a list of customers and prints a report with customer names.

Listing 3-6 Declaring a method that takes parameters

C# (Program.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram
{
    class Program
    {
         static void Main(string[] args)
     {
         MessagePrinter msgPrint = new MessagePrinter();

         string[]   customerNames =  {  "Jones",   "Smith",   "Mayo" };
         string reportTitle = "Important Customer Report";

         msgPrint.PrintCustomerReport(customerNames, reportTitle);
     }
}

C# (MessagePrinter.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram
{
        public void PrintCustomerReport(
            string[]   customers,   string title = "Customer Report")
        {
            Console.WriteLine(title);
            Console.WriteLine();

            foreach  (var name in customers)
            {
                Console.WriteLine(name);
            }
        }
    }
}

VB (Modulel.vb):

Module Module1
   Sub Main()
       Dim msgPrint As New MessagePrinter()

       Dim customerNames =  {"Jones",   "Smith", "Mayo"}
       Dim reportTitle As String = "Important Customer Report"

       msgPrint.PrintCustomerReport(customerNames, reportTitle)
    End Sub
End Module

VB (MessagePrinter.vb):

Public Class MessagePrinter
    Sub PrintCustomerReport(ByVal customers As String(), ByVal title
As String)
        Console.WriteLine(title)
        Console.WriteLine()

        For Each name In customers
            Console.WriteLine(name)
        Next
    End Sub
End Class

Parameters are a comma-separated list of identifiers, along with the type of each identifier, which clearly indicates what type of parameter the method is expecting. In Listing 3-6, the PrintCustomerReport method has two parameters: title of type string and customers of type string array. The method displays the title in the console window when you run the program, displays a blank line, and then iterates through the list, displaying each customer name to the console.

You can see how the Main method creates a new instance of MessagePrinter, which msgPrint points to, and then calls PrintCustomerReport using msgPrint. The arguments being passed, reportTitle and customerNames, match the position and types of the parameters for PrintCustomerReport, which are of the correct types that the PrintCustomerReport method is expecting.

In the preceding example, the calling code must provide arguments, actual data, for all parameters. However, you can specify parameters as being optional, allowing you to omit arguments for the optional parameters if you like. Here’s a modification to PrintCustomerReport where the title becomes an optional parameter:

C#:

public void PrintCustomerReport(
    string[]   customers,   string title = "Customer Report")
{
    Console.WriteLine(title);
    Console.WriteLine();

    foreach  (var name in customers)
    {
        Console.WriteLine(name);
    }
}

VB:

Sub PrintCustomerReport(
    ByVal customers As String(),
    Optional ByVal title As String = "Customer Report")

    Console.WriteLine(title)
    Console.WriteLine()

    For Each name In customers
        Console.WriteLine(name)
    Next
End Sub

The preceding code requires callers to pass an array of customers, but it does not require a title. When writing methods, optional parameters must be listed last. Here’s a method call without the optional parameter:

C#:

custProg.PrintCustomerReport(customerNames);

VB:

msgPrint.PrintCustomerReport(customerNames)

Because the caller didn’t pass an argument for title, the value of title inside of PrintCustomerReport becomes the default value assigned to the title parameter.

In addition to passing arguments to methods, you can receive values returned from methods.

Returning Data and Using Method Results

It is common to call methods that return values. To demonstrate the proper syntax, Listing 3-7 contains a method that accepts an int and returns the squared value of that int. Calling code then assigns the return value from the method to a variable and displays the value on the console window. Create a new class named Calc.cs or Calc. vb to hold the new method.

Listing 3-7 Returning values from methods

C# (Program.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            Calc mathProg = new Calc();

            int squaredInt = mathProg.SquareInt(3);
            Console.WriteLine("3 squared is " + squaredInt);

            Console.ReadKey();
         }
     }
}

C# (Calc.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram
{
    public class Calc
    {
        public int SquareInt(int number)
        {
           return number * number;
        }
    }
}

VB (Modulel.vb):

Module Module1

   Sub Main()
       Dim mathProg As New Calc()
       Dim squaredInt As Integer = mathProg.SquareInt(3)
       Console.WriteLine("3 squared is "  & squaredInt)
   End Sub
End Module

Image

Figure 3-2 The VB sub snippet template

VB (Calc.vb):

Public Class Calc
   Public Function SquareInt(ByVal number As Integer) As Integer
       Return number * number
   End Function
End Class

For the C# example, notice how the return type of the SquareInt method is type int, rather than the keyword void that was used in our methods before. Whenever you specify a return type, the method must return something whose type is the same as the return type declared. In the preceding example, the return type is declared as int; therefore, the method guarantees that the result of the calculation is type int. The Main method has a couple of statements that invoke this method and display the results to the console.

In the VB example, the method is now a Function. Sub methods don’t return values. Notice how the function signature appends As Integer after the parameter list, which indicates that the return type of the function is Integer.

Method Snippets

C# doesn’t have snippets for writing methods (although you could create your own snippets), but VB does. In VB, type Sub, TAB, TAB; producing the template shown in Figure 3-2; or Fun, TAB, TAB; producing the template shown in Figure 3-3.

Image

Figure 3-3 The VB function snippet template

Coding Fields and Properties

A field is a variable that is a member of a class (type), as opposed to variables that are declared inside of methods, which are called local variables or locally scoped variables. Properties are type members that give you functionality that is a cross between fields and methods. You can read and write to a property just as you can to a field. Additionally, you can define code that runs whenever you read to or write from a property, similar to methods. The following sections define fields and properties.

Declaring and Using Fields

As stated, a field is a variable that is a member of a class (or some other container, such as a struct, which is very similar to a class). This provides the benefit of having the field and the data it contains available to all of the other members of the class (as well as to any deriving classes, via inheritance, depending on the field’s access modifier). To demonstrate how a field is declared and used, the example in Listing 3-8 simulates a bank account that has a field of type decimal named currentBalance, which holds an account balance. The class has two methods: Credit and Debit. Credit increases the value of currentBalance, and Debit decreases the value of currentBalance.

Listing 3-8 Using fields and properties

C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstProgram
{
    class Program
    {
        private decimal accountBalance = 100m;

        static void Main(string[] args)
        {
            Program account = new Program();
            account.Credit(100m);
            account.Debit(50m);
            Console.WriteLine("Balance: " + account.CurrentBalance);

            Console.ReadKey();
        }
        public void Credit(decimal amount)
        {
           accountBalance += amount;
        }

        public void Debit(decimal amount)
        {
           accountBalance -= amount;
        }

        public decimal CurrentBalance
        {
            get
            {
                return accountBalance;
            }
            set
            {
                if  (value < 0)
                {
                     // charge fee
                }
                accountBalance = value;
            }
        }
    }
}

VB:

Module Module1
Private Dim accountBalance As Decimal = 100
    Sub Main()        Credit(100)
        Debit(50)
        Console.WriteLine("Balance:   "  & CurrentBalance)

        Console.ReadKey()
    End Sub

    Sub Credit(ByVal amount As Decimal)
        accountBalance += amount
    End Sub

    Sub Debit(ByVal amount As Decimal)
        accountBalance -= amount
    End Sub
    Public Property CurrentBalance()  As Decimal
        Get
            Return accountBalance
    End Get
    Set(ByVal value As Decimal)

            If value < 0 Then
                 ' charge fee
            End If

            accountBalance = value
        End Set
    End Property
End Module

Look at where accountBalance is declared: at the beginning of the Program (Modulel in VB) class block. It is at the same scope as Main and other methods, meaning that it is a member of Program (Modulel in VB), just like Main, Credit, and Debit. When variables like accountBalance are declared as class members, as opposed to local variables that are declared inside of method blocks, they are called fields. The accountBalance is type decimal, which is a good choice for holding financial values.

The accountBalance field has a private modifier, which means that it can only be used by members of the same class. The implementations of Credit and Debit, respectively, increase and decrease the value of accountBalance. Since Credit and Debit are members of the same class as accountBalance, they’re allowed to read from and write to accountBalance.

Main invokes Credit and Debit to change the value of the accountBalance field. Additionally, Main displays the value of accountBalance in the console window through a property named CurrentBalance. The next section explains how the CurrentBalance property works.

Declaring and Using Properties

Properties are class members that you use just like a field, but the difference is that you can add specialized logic when reading from or writing to a property. Listing 3-8 contains an example of a property, CurrentBalance, repeated as follows for your convenience:

C#:

public decimal CurrentBalance
{
    get
    {
        return accountBalance;
    }
    set
    {
        if   (value < 0)
        {
             // charge fee
        }
        accountBalance = value;
    }

VB:

Public Property CurrentBalance()  As Decimal
   Get
       Return accountBalance
   End Get
   Set(ByVal value As Decimal)

        If value < 0 Then
           ' charge fee
        End If

        accountBalance = value
    End Set
End Property

Properties have accessors, named get and set, that allow you to add special logic when the property is used. When you read from a property, only the get accessor code executes, and the set accessor code only executes when you assign a value to a property. In the preceding example, the get accessor returns the value of currentBalance with no modifications. If there were some logic to apply, like calculating interest in addition to the current balance, the get accessor might have contained the logic for that calculation prior to returning the value. The set accessor does have logic that checks the value to see if it is less than zero, which could happen if a customer overdrew his or her account. If the value is less than zero, then you could implement logic to charge the customer a fee for the overdraft. The value keyword contains the value being assigned to the property, and the previous set accessor assigns value to the accountBalance field. The following statement from the Main method in Listing 3-8 reads from CurrentBalance, effectively executing the get accessor, which returns the value of currentBalance:

C#:

Console.WriteLine("Balance:   " + account.CurrentBalance);

VB:

Console.WriteLine("Balance:   "  & CurrentBalance)

Since the CurrentBalance property returns the value of the accountBalance field, the Console.WriteLine statement will print the value read from CurrentBalance to the command line.

Many of the properties you’ll write will simply be wrappers around current object state with no other logic, as in Listing 3-9.

Listing 3-9 Property that wraps object state with no logic

C#:

private string m_firstName;

public string FirstName
{
    get
    {
        return m_firstName;
    }
    set
    {
        m_firstName = value;
    }
}

VB:

Private m_firstName As String
Public Property FirstName()  As String
    Get
        Return m_firstName
    End Get
    Set(ByVal value As String)
        m_firstName = value
    End Set
End Property

In Listing 3-9, you can see that m_firstName, commonly referred to as a backing field, is a private variable and that the FirstName property only returns m_firstName from the get accessor and assigns the value to mJirstName in the set accessor. Since this is so common, you can save syntax by using an automatic property, as shown in Listing 3-10.

Listing 3-10 Auto-implemented properties

C#:

public string FirstName  { get;   set; }

VB:

Public Property FirstName As String

Image

Figure 3-4 The C# property snippet template

The automatic property, FirstName, is logically equivalent to the expanded FirstName with accessors and backing field. Behind the scenes, the compiler produces the expanded version where the backing field is guaranteed to have a unique name to avoid conflicts. Do not overlook that when you use automatic properties, you cannot add your own code that runs inside the get or set accessors.

The Property Snippet

To create a property snippet, type pro and press TAB, TAB; and you’ll see the property snippet template shown in Figure 3-4 for C# or Figure 3-5 for VB.

A C# property snippet template creates an automatic property by default, but the VB snippet template is a normal property with full get and set accessors.

Image

Figure 3-5 The VB property snippet template

Summary

You are now able to create classes to define your own custom types. After learning how to create classes and use class instances, also known as objects, you learned how to add fields, methods, and properties to your class definition. The methods discussion was more in-depth, showing you how to define parameters and return values. You also learned how to define both auto-implemented and normal properties, and you learned a little about class inheritance.

The next chapter moves you up a level in language skills by showing you how to create another type, called an interface. You’ll also learn how to add another type of class member, events.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.26.176