modern software development using c#.net chapter 5: more advanced class construction

36
Modern Software Development Using C# .NET Chapter 5: More Advanced Class Construction

Upload: ashlynn-neal

Post on 03-Jan-2016

216 views

Category:

Documents


1 download

TRANSCRIPT

Modern Software Development Using C# .NET

Chapter 5: More Advanced Class Construction

Modern Software Development Using C# .NET by Richard Wiener 2

Overview

• Some common pitfalls associated with class construction are examined and solutions found to the problems.

• We look at constructor pitfalls, redefining the Equals method from class Object, cloning objects, using StringBuilder instead of String objects, the important and new feature of generic classes and the new and important feature of enumerators that enable the use of the foreach iteration for the instances of a class.

Modern Software Development Using C# .NET by Richard Wiener 3

Avoiding protected fields

• Fields earmarked as protected in a base class are directly accessible in all descendent classes.

• Assignment to a base-class field made in a remote descendent class, many levels down in a class hierarchy, may not be easy to decipher and understand unless the programmer making this field assignment has intimate knowledge of the base class that contains the field whose value is being modified.

Modern Software Development Using C# .NET by Richard Wiener 4

Avoiding protected fields continued

• Another consequence of making direct assignments to base-class fields in a descendent class is that if in the future the information structure of the base class is changed and the base-class field is removed, the descendent classes that have made direct assignments to this base-class field will be broken.

Modern Software Development Using C# .NET by Richard Wiener 5

Constructor pitfall

• Never invoke a method within a base-class constructor that can be redefined in some descendent class.

Modern Software Development Using C# .NET by Richard Wiener 6

Overriding method Equals from class Object

• When designing classes for potential reuse in many applications, it is important to consider whether it is appropriate to redefine the Equals method inherited by default from class Object.

• The default Equals method from Object considers two objects to be equal in value if and only if they have the same memory reference.

• Often this default meaning of Equals is incorrect.

Modern Software Development Using C# .NET by Richard Wiener 7

Cloning objects

• Cloning an object involves producing a new instance of a class, the target, and copying the features of the source instance to the target instance.

• An important issue is whether the target instance continues to have any dependence on the source object. In principle, it should not. In practice, it often does which can be a major problem.

Modern Software Development Using C# .NET by Richard Wiener 8

Cloning objects continued

• There are two types of copying: shallow and deep copying.

• Shallow copying copies references but not the content of the references.

• As a result the target reference becomes another name for the source reference.

• Any change made to the source or target after the copy affects the other.

• With deep copying, an independent autonomous target is created with the content of the source copied to the target and with no residual dependency between the source and the target.

Modern Software Development Using C# .NET by Richard Wiener 9

Cloning objects continued

• When one reference-type object, say object1 is assigned to another reference-type object, say object2, as in,

object2 = object1;

a shallow copy results. Any subsequent change to object1 appears to affect object2 since they are both names for the same storage.

Modern Software Development Using C# .NET by Richard Wiener 10

Cloning objects continued

• Any C# class that defines a Clone method must implement the interface IClonable. This interface is given as follows:

public interface IClonable {

Object Clone();

}

Modern Software Development Using C# .NET by Richard Wiener 11

Using StringBuilder instead of String • A common and potentially expensive pitfall is using

objects of type String instead of StringBuilder when repeatedly concatenating string objects.

• Objects of type String are immutable. That means that once a String object is constructed its contents cannot be changed. String objects are of value type.

• Standard class StringBuilder presents a mutable reference type that may be used as an alternative to String when appropriate.

Modern Software Development Using C# .NET by Richard Wiener 12

Generics

• A generic container class contains a set of operations that are independent of the type of objects being held in the container.

• With the advent of object-oriented languages and an omnipresent class Object that all classes are descendents of, the temptation to achieve generic behavior through polymorphism has been present.

• In a landmark paper “Genericity versus Inheritance” published in the ACM SIGPLAN Notices, Vol 21, No 11 in 1986, Bertrand Meyer presents a clear case that using polymorphism through inheritance to achieve generic behavior is the wrong way to achieve generic behavior.

Modern Software Development Using C# .NET by Richard Wiener 13

Generics continued

• A class is generic if it contains one or more generic parameters. When an instance of such a class is created, the specific type for each generic parameter must be specified.

• Consider the signature of the following generic class:

public class MyGenericClass<T> {// Details not shown

}

An instance of this class may be created as follows:

MyGenericClass<String> myObject = new MyGenericClass<String>();

Here the generic parameter T is replaced by String.

Modern Software Development Using C# .NET by Richard Wiener 14

Constrained generic parameters

• The parameters specified in a generic class may be constrained.

• A generic parameter may be constrained by specifying that it must implement a particular interface or extend a particular class.

Modern Software Development Using C# .NET by Richard Wiener 15

Constrained generic parameters continued

• Consider the following class declaration:

public class MyGenericClass<T> : IComparable where T :

IComparable {// Details not shown

}

This declaration implies that MyGenericClass contains a generic parameter T that must implement the IComparable interface. In addition, the class itself must implement this interface (define a method CompareTo).

Modern Software Development Using C# .NET by Richard Wiener 16

Generic methods

• Methods may be defined that contain one or more generic parameters even though the class that they are defined within contains no generic parameters.

• Consider the static method SelectionSort that contains the constrained generic parameter T. Its signature is the following:

public static void SelectionSort<T>(T [] data, int size) where T : IComparable

{// Details not shown

}

Modern Software Development Using C# .NET by Richard Wiener 17

Generic methods continued

• The constraint on the generic parameter T is that it must be an instance of a class that implements the IComparable interface.

• This makes sense because to sort an array of values, the values must be comparable otherwise there would be no way to determine the smallest, next smallest, etc.

Modern Software Development Using C# .NET by Richard Wiener 18

Summary of the benefits of generic classes

• Generic container classes move type checking from the runtime system to the compiler, thus making code safer.

• They also provide for a mechanism for self-documentation since when a generic container instance is created, the type of objects that are intended to be placed inside the container is specified in the code itself.

• Finally, generic classes remove the need for cluttering one’s code with downcasts. This makes the code easier to read and maintain.

Modern Software Development Using C# .NET by Richard Wiener 19

Enumerators

• Iteration through a container class allows each object in the container to be visited exactly once.

• Any class that is to support an enumerator must implement the IEnumerable interface.

• Such a class must meet the contract of implementing the GetEnumerator method that returns an instance of IEnumerator.

Modern Software Development Using C# .NET by Richard Wiener 20

Enumerators continued

• A class that implements IEnumerator must meet the contract of implementing:• The read-only property Current that returns the

element in the collection that the cursor is currently pointing to.

• The method MoveNext that returns a value true if the enumerator has successfully advanced to the next element in the collection and false if there is no next element in the collection.

• The method Reset that restores the cursor so that it points to the first element in the collection.

Modern Software Development Using C# .NET by Richard Wiener 21

Enumerators continued

• The foreach construct provides a simple

mechanism for iterating through a collection object that is an instance of a class that implements IEnumerable.

Modern Software Development Using C# .NET by Richard Wiener 22

Enumerators continued

• We illustrate the use of the foreach construct on the standard ArrayList collection class in the following segment of code.

• An ArrayList containing four objects of type String is created. Using the foreach iteration construct, the names are output.

Modern Software Development Using C# .NET by Richard Wiener 23

Enumerators continued

using System;using System.Collections;namespace Iteration { public class IterationApplication { static void Main() { ArrayList myList = new ArrayList(); myList.Add("Erik"); myList.Add("Anna"); myList.Add("Marc"); myList.Add("Daniel"); foreach (String name in myList) { Console.WriteLine(name); } Console.ReadLine(); } }}

Modern Software Development Using C# .NET by Richard Wiener 24

Enumerators continued

• An alternative way to iterate through the ArrayList would be:

IEnumerator iterator = myList.GetEnumerator();bool result = iterator.MoveNext();while (result && iterator.Current != null) {

String name = (String)iterator.Current;Console.WriteLine(name);result = iterator.MoveNext();

}

The foreach construct clearly provides a simpler mechanism for accomplishing the iteration through the ArrayList container.

Modern Software Development Using C# .NET by Richard Wiener 25

Partial classes

• C# allows a class definition to be distributed over several source files.

• Integrated development environments such as Visual Studio take advantage of this capability by embedding initialization code in a separate file from the code the user develops even though both are part of the same class.

Modern Software Development Using C# .NET by Richard Wiener 26

Partial classes continued

• The keyword partial is used to achieve this. So, for example, MyClass might be written in several parts by using,

public partial class MyClass {

// Details not shown

}

Modern Software Development Using C# .NET by Richard Wiener 27

Summary

• Fields earmarked as protected in a base class are directly accessible in all descendent classes.

• As a consequence, an assignment to a base-class field made in a remote descendent class, many levels down in a class hierarchy, may not be easy to decipher and understand unless the programmer making this field assignment has intimate knowledge of the base class that contains the field whose value is being modified.

Modern Software Development Using C# .NET by Richard Wiener 28

Summary continued

• Never invoke a method within a base-class constructor that can be redefined in some descendent class.

• When designing classes for potential reuse, it is important to consider whether it is appropriate to redefine the Equals method inherited by default from class Object.

• The default Equals method from Object considers two objects to be equal in value if and only if they have the same memory reference.

• Often this default meaning of Equals is incorrect.

Modern Software Development Using C# .NET by Richard Wiener 29

Summary continued

There are two types of copying: shallow and deep copying.

The former copies references but not the content of the references.

As a result, the target reference becomes another name for the source reference. Any change made to the source or target after the copy affects the other.

With deep copying, an independent autonomous target is created with the content of the source copied to the target and with no residual dependency between the source and the target.

Modern Software Development Using C# .NET by Richard Wiener 30

Summary continued

• Never implement a Clone method by invoking the constructor of the containing class.

• A common and potentially expensive pitfall is using objects of type String instead of StringBuilder when repeatedly concatenating string objects.

• Objects of type String are immutable. That means that once a String object is constructed, its contents cannot be changed.

• String objects are of value type. • Standard class StringBuilder presents a mutable reference type

that may be used as an alternative to String when appropriate.

Modern Software Development Using C# .NET by Richard Wiener 31

Summary continued

In a landmark paper “Genericity versus Inheritance” published in the ACM SIGPLAN Notices, Vol 21, No 11 in 1986, Bertrand Meyer presents a clear case that using polymorphism through inheritance to achieve generic behavior is the wrong way to achieve generic behavior.

Modern Software Development Using C# .NET by Richard Wiener 32

Summary continued

The use of generic container classes provides for more readable code.

When a generic instance is created, the programmer’s intentions are documented in the code itself.

Any attempt on the part of the programmer to insert an object whose type differs from the type specified when the instance of the generic container is created produces a compile-time error.

This is better than a runtime error that would occur when using the older approach to constructing generic containers.

Discovering errors at compile time is always superior to discovering errors at runtime.

Modern Software Development Using C# .NET by Richard Wiener 33

Summary continued

• The parameters specified in a generic class may be constrained. A generic parameter may be constrained by specifying that it must implement a particular interface or extend a particular class.

• Methods may be defined that contain one or more generic parameters even though the class that they are defined within contains no generic parameters.

Modern Software Development Using C# .NET by Richard Wiener 34

Summary continued

• Generic container classes move type-checking from the runtime system to the compiler thus making code safer.

• Generic classes provide for a mechanism for self-documentation since when a generic container instance is created, the type of objects that are intended to be placed inside the container is specified in the code itself.

• Generic classes remove the need for cluttering one’s code with downcasts. This makes the code easier to read and maintain.

Modern Software Development Using C# .NET by Richard Wiener 35

Summary continued

• Iteration through a container class allows each object in the container to be visited exactly once.

• Any class that is to support an enumerator must implement the IEnumerable interface.

• Such a class must meet the contract of implementing the GetEnumerator method that returns an instance of IEnumerator.

Modern Software Development Using C# .NET by Richard Wiener 36

Summary continued

• A class that implements IEnumerator must meet the contract of implementing: • The read-only property Current that returns the element in

the collection to which the cursor is currently pointing. • The method MoveNext that returns a value true if the

enumerator has successfully advanced to the next element in the collection and false if there is no next element in the collection.

• The method Reset that restores the cursor so that it points to the first element in the collection.