10.14 Time Class Case Study: Extension Methods

You can use extension methods to add functionality to an existing type without modifying the type’s source code. You saw in Section 9.3.3 that LINQ’s capabilities are implemented as extension methods. Figure 10.16 uses extension methods to add two new methods to class Time2 (Section 10.5)—DisplayTime and AddHours.

Fig. 10.16 Demonstrating extension methods.

Alternate View

 1    // Fig. 10.16: TimeExtensionsTest.cs
 2    // Demonstrating extension methods.
 3    using System;
 4
 5    class TimeExtensionsTest
 6    {
 7    static void Main()
 8    {
 9       var myTime = new Time2(); // call Time2 constructor
10       myTime.SetTime(11,34, 15); // set the time to 11:34:15
11
12       // test the DisplayTime extension method
13       Console.Write("Use the DisplayTime extension method: ");
14       myTime.DisplayTime();
15
16       // test the AddHours extension method
17       Console.Write("Add 5 hours with the AddHours extension method: ");
18       var timeAdded = myTime.AddHours(5); // add five hours   
19       timeAdded.DisplayTime(); // display the new Time2 object
20
21       // add hours and display the time in one statement
22       Console.Write("Add 15 hours with the AddHours extension method: ");
23       myTime.AddHours(15).DisplayTime(); // add hours and display time
24
25       // use fully qualified extension-method name to display the time
26       Console.Write("Use fully qualified extension-method name: ");
27       TimeExtensions.DisplayTime(myTime);
28      }
29     }
30
31    // extension-methods class
32    static class TimeExtensions
33    {
34        // display the Time2 object in console
35        public static void DisplayTime(this Time2 aTime)
36        {
37           Console.WriteLine(aTime.ToString());
38        }
39
40        // add the specified number of hours to the time
41        // and return a new Time2 object
42        public static Time2 AddHours(this Time2 aTime, int hours )
43       {
44         // create a new Time2 object
45         var newTime = new Time2() {
46            Minute = aTime.Minute, Second = aTime.Second};
47
48         // add the specified number of hours to the given time
49         newTime.Hour = (aTime.Hour + hours) % 24;
50
51         return newTime; // return the new Time2 object
52       }
53     }

Use the DisplayTime extension method: 11:34:15 AM
Add 5 hours with the AddHours extension method: 4:34:15 PM
Add 15 hours with the AddHours extension method: 2:34:15 AM
Use fully qualified extension-method name: 11:34:15 AM

Extension Method DisplayTime

The extension method DisplayTime (lines 35–38) displays the string representation of the time in the console window. The key new feature of method DisplayTime is the this keyword that precedes the Time2 parameter in the method header (line 35)—this notifies the compiler that DisplayTime is an extension method for an existing class (Time2). The type of an extension method’s first parameter specifies the type of object on which you can call the method—for this reason, each extension method must define at least one parameter. Also, extension methods must be defined as static methods in a static class such as TimeExtensions (lines 32–53). A static class can contain only static members and cannot be instantiated.

Calling Extension Method DisplayTime

Line 14 uses Time2 object myTime to call the DisplayTime extension method. Note that we do not provide an argument to the method call. The compiler implicitly passes the object that calls the method (myTime) as the extension method’s first argument. This allows you to call DisplayTime as if it were a Time2 instance method. In fact, IntelliSense displays extension methods with the class’s instance methods and identifies them with a distinct icon

The down-arrow in the icon denotes an extension method. Also, when you select an extension method in the IntelliSense window, the tool tip that describes the method includes the text (extension) for each extension method.

Extension Method AddHours

Lines 42–52 of Fig. 10.16 declare the AddHours extension method. Again, the this keyword in the first parameter’s declaration indicates that AddHours can be called on a Time2 object. The second parameter is an int value specifying the number of hours to add to the time. The AddHours method returns a new Time2 object with the specified number of hours added.

Lines 45–46 create the new Time2 object and use an object initializer to set its Minute and Second properties to the corresponding values in the parameter aTime—these are not modified when we add hours to the time. Line 49 adds the second argument’s number of hours to the original Time2 object’s Hour property, then uses the % operator to ensure the value remains in the range 0–23. The result is assigned to the new Time2 object’s Hour property. Line 51 returns the new Time2 object to the caller.

Calling Extension Method AddHours

Line 18 calls the AddHours extension method to add five hours to the myTime object’s hour value. Note that the method call specifies only one argument—the number of hours to add. Again, the compiler implicitly passes the object that’s used to call the method (my-Time) as the extension method’s first argument. The Time2 object returned by AddHours is assigned to a local variable (timeAdded) and displayed in the console using the Display-Time extension method (line 19).

Calling Both Extension Methods in a Single Statement

Line 23 uses both extension methods (DisplayTime and AddHours) in a single statement to add 15 hours to the original myTime and display the result in the console. Multiple method calls in the same statement are known as cascaded method calls. When a method returns an object, you can follow the method call with a member access operator (.) then call a method on the object that was returned. The methods are called from left to right. In line 23, the DisplayTime method is called on the Time2 object returned by method AddHours. This eliminates the need to assign the object returned by AddHours to a variable, then call DisplayTime in a separate statement.

Calling an Extension Method With Its Fully Qualified Name

Line 27 calls extension method DisplayTime using its fully qualified name—the name of the class in which the extension method is defined (TimeExtensions), followed by the member access operator (.), the method name (DisplayTime) and its argument list. Note in line 27 that the call to DisplayTime passes a Time2 object as an argument to the method. When using the fully qualified method name, you must specify an argument for extension method’s first parameter. This use of the extension method uses the syntax of a static method call.

Extension Method Cautions

If a type for which you declare an extension method already defines an instance method with the same name and a compatible signature, the instance method will shadow (i.e., hide) the extension method. Also, if a predefined type is later updated to include an instance method that shadows an extension method, the compiler does not report any errors and the extension method does not appear in IntelliSense.

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

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