Using the this Keyword


Using the this Keyword

You can obtain the reference to a class from within instance members that belong to the class. To indicate explicitly that the field or method accessed is an instance member of the containing class in C#, you use the keyword this.this is simply an implicit field within every class definition that returns an instance of the object itself.

For example, consider the SetName() method shown in Listing 5.9.

Listing 5.9. Using this to Identify the Field's Owner Explicitly

 class Employee {   public string FirstName;   public string LastName;   public string Salary;   public string GetName()   {       return FirstName + " " + LastName;   }   public void SetName(string newFirstName, string newLastName)          {                                                                         this.FirstName = newFirstName;                                        this.LastName = newLastName;                                      }                                                                   } 

This example uses the keyword this to indicate that the fields FirstName and LastName are instance members of the class.

Language Contrast: Visual BasicAccessing a Class Instance with Me

The C# keyword this is identical to the Visual Basic keyword Me.


You also can use the keyword this to access a class's methods explicitly. this.GetName() is allowed within the SetName() method, for example, allowing you to print out the newly assigned name (see Listing 5.10 and Output 5.3).

Listing 5.10. Using this with a Method

[View full width]

 class Employee {    // ...    public string GetName()    {        return FirstName + " " + LastName;    }       public void SetName(string newFirstName, string newLastName)    {        this.FirstName = newFirstName;        this.LastName = newLastName;        Console.WriteLine("Name changed to '{0}'",                                                                 this.GetName());                                             } } class Program {    static void Main()    {          Employee employee = new Employee();          employee.SetName("Inigo", "Montoya");         // ...    }    // ... } 

Output 5.3.

 Name changed to 'Inigo Montoya' 

In Listing 5.9 and Listing 5.10, the this keyword is optional, as demonstrated in the GetName() method where this is not used. However, if local variables or parameters exist with the same name as the field, then leaving off this would result in accessing the local variable/parameter rather than the field, so this would be required.

Beginner Topic: Relying on Coding Style to Avoid Ambiguity

In the SetName() method, you did not have to use the this keyword because FirstName is obviously different from newFirstName. Consider, however, if instead of calling the parameter "newFirstName" you called it "FirstName" (using Pascal case), as shown in Listing 5.11.

Listing 5.11. Using this to Avoid Ambiguity

 class Employee {   public string FirstName;   public string LastName;   public string Salary;   public string GetName()   {       return FirstName + " " + LastName;   }   // Caution:Parameter names use Pascal case   public void SetName(string FirstName, string LastName)   {       this.FirstName = FirstName;       this.LastName = LastName;   } } 

In this example, it is not possible to refer to the FirstName field without explicitly indicating that the Employee object owns the variable. this acts just like the employee1 variable prefix used in the Program.Main() method (see Listing 5.8); it identifies the reference as the one on which SetName() was called.

Listing 5.11 does not follow the C# naming convention in which parameters are declared like local variables, using camel case. This can lead to subtle bugs because assigning FirstName (intending to refer to the field) to FirstName (the parameter) will still compile and even run. To avoid this problem it is a good practice to have a different naming convention for parameters and local variables than the naming convention for fields. I demonstrate one such convention later in this chapter.


Sometimes it may be necessary to use this in order to pass a reference to the currently executing object. Consider the Save() method in Listing 5.12.

Listing 5.12. Passing this in a Method Call

 class Employee {   public string FirstName;   public string LastName;   public string Salary;   public void Save()   {       DataStorage.Store(this);                               } } class DataStorage   {      // Save an employee object to a file      // named with the Employee name.      public static void Store(Employee employee)     {          // ...     }   } 

The Save() method calls a method on the DataStorage class, called Store(). The Store() method, however, needs to be passed the Employee object that needs to be persisted. This is done using the keyword this, which passes the instance of the Employee object on which Save() was called.

Advanced Topic: Storing and Loading with Files

The actual implementation of the Store() method inside DataStorage involves classes within the System.IO namespace, as shown in Listing 5.13. Inside Store(), you begin by instantiating a FileStream object that you associate with a file corresponding to the employee's full name. The FileMode.Create parameter indicates that you want a new file to be created if there isn't already one with the <firstname><lastname>.dat name; if the file exists already, it will be overwritten. Next, you create a StreamWriterclass. The StreamWriter class is responsible for writing text into the FileStream. You write the data using WriteLine() methods, just as though writing to the console.

Listing 5.13. Data Persistence to a File

 using System; // IO namespace using System.IO; class DataStorage {    // Save an employee object to a file    // named with the Employee name.    // Error handling not shown.    public static void Store(Employee employee)   {     // Instantiate a FileStream using FirstNameLastName.dat     // for the filename. FileMode.Create will force     // a new file to be created or override an     // existing file.     FileStream stream = new FileStream(         employee.FirstName + employee.LastName + ".dat",         FileMode.Create);     // Create a StreamWriter object for writing text     // into the FileStream     StreamWriter writer = new StreamWriter(stream);     // Write all the data associated with the employee.     writer.WriteLine(employee.FirstName);     writer.WriteLine(employee.LastName);     writer.WriteLine(employee.Salary);     // Close the StreamWriter and its Stream.     writer.Close();     stream.Close();   }    // ... } 

Once the write operations are completed, both the FileStream and the StreamWriter need to be closed so that they are not left open indefinitely while waiting for the garbage collector to run. This listing does not include any error handling, so if an exception is thrown, neither Close() method will be called.

The load process is similar (see Listing 5.14).

Listing 5.14. Data Retrieval from a File

 // IO namespace using System; using System.IO; class DataStorage {    // ...        public static Employee Load(string firstName, string lastName)    {        Employee employee = new Employee();        // Instantiate a FileStream using FirstNameLastName.dat        // for the filename. FileMode.Open will open      // an existing file or else report an error.      FileStream stream = new FileStream(          firstName + lastName + ".dat", FileMode.Open);      // Create a SteamReader for reading text from the file.      StreamReader reader = new StreamReader(stream);      // Read each line from the file and place it into      // the associated property.      employee.FirstName = reader.ReadLine();      employee.LastName = reader.ReadLine();      employee.Salary = reader.ReadLine();      // Close the StreamReader and its Stream.      reader.Close();      stream.Close();      return employee;    }  } 

The reverse of the save process appears in Listing 5.14, which uses a StreamReader rather than a StreamWriter. Again, Close() needs to be called on both FileStream and StreamReader once the data has been read.

Observe the inclusion of the using System.IO directive at the top of the listing. This makes each IO class accessible without prefixing it with the full namespace.





Essential C# 2.0
Essential C# 2.0
ISBN: 0321150775
EAN: 2147483647
Year: 2007
Pages: 185

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net