The Object Class


As indicated earlier, all .NET classes are ultimately derived from System.Object. In fact, if you don't specify a base class when you define a class, the compiler will automatically assume that it derives from Object. Because inheritance has not been used in this chapter, every class you have seen here is actually derived from System.Object. (As noted earlier, for structs this derivation is indirect: A struct is always derived from System.ValueType, which in turn derives from System.Object.)

The practical significance of this is that, besides the methods and properties and so on that you define, you also have access to a number of public and protected member methods that have been defined for the Object class. These methods are available in all other classes that you define.

System.Object Methods

The methods defined in Object are as shown in the following table:

Method

Access Modifiers

Purpose

string ToString()

public virtual

Returns a string representation of the object

int GetHashTable()

public virtual

Used if implementing dictionaries (hash tables)

bool Equals(object obj)

public virtual

Compares instances of the object for equality

bool Equals(object objA, object objB)

public static

Compares instances of the object for equality

bool ReferenceEquals (object objA, object objB)

public static

Compares whether two references refer to the same object

Type GetType()

Public

Returns details of the type of the object

object MemberwiseClone()

Protected

Makes a shallow copy of the object

void Finalize()

protected virtual

This is the .NET version of a destructor

You haven't yet seen enough of the C# language to be able to understand how to use all these methods. For the time being, the following list simply summarizes the purpose of each method, with the exception of ToString(), which is examined in more detail.

  • ToString() — This is intended as a fairly basic, quick-and-easy string representation; use it when you just want a quick idea of the contents of an object, perhaps for debugging purposes. It provides very little choice of how to format the data: For example, dates can in principle be expressed in a huge variety of different formats, but DateTime.ToString() does not offer you any choice in this regard. If you need a more sophisticated string representation that, for example, takes account of your formatting preferences or of the culture (the locale), then you should implement the IFormattable interface (see Chapter 8, "Strings and Regular Expressions").

  • GetHashCode() — This is used if objects are placed in a data structure known as a map (also known as a hash table or dictionary). It is used by classes that manipulate these structures in order to determine where to place an object in the structure. If you intend your class to be used as key for a dictionary, you will need to override GetHashCode(). Some fairly strict requirements exist for how you implement your overload, and you learn about those when you examine dictionaries in Chapter 9, "Collections."

  • Equals() (both versions) and ReferenceEquals() — As you'll gather by the existence of three different methods aimed at comparing the equality of objects, the .NET Framework has quite a sophisticated scheme for measuring equality. Subtle differences exist between how these three methods, along with the comparison operator, ==, are intended to be used. Not only that, but restrictions also exist on how you should override the virtual, one-parameter version of Equals() if you choose to do so, because certain base classes in the System.Collections namespace call the method and expect it to behave in certain ways. You explore the use of these methods in Chapter 5, "Operators and Casts," when you examine operators.

  • Finalize() — This method is covered in Chapter 7, "Memory Management and Pointers." It is intended as the nearest that C# has to C++-style destructors, and is called when a reference object is garbage collected to clean up resources. The Object implementation of Finalize() actually does nothing and is ignored by the garbage collector. You will normally override Finalize() if an object owns references to unmanaged resources that need to be removed when the object is deleted. The garbage collector cannot do this directly because it only knows about managed resources, so it relies on any finalizers that you supply.

  • GetType() — This method returns an instance of a class derived from System.Type. This object can provide an extensive range of information about the class of which your object is a member, including base type, methods, properties, and so on. System.Type also provides the entry point into .NET's reflection technology. Chapter 11, "Reflection," examines this topic.

  • MemberwiseClone() — This is the only member of System.Object that isn't examined in detail anywhere in the book. There is no need to, because it is fairly simple in concept. It simply makes a copy of the object and returns a reference (or in the case of a value type, a boxed reference) to the copy. Note that the copy made is a shallow copy — this means that it copies all the value types in the class. If the class contains any embedded references, then only the references will be copied, not the objects referred to. This method is protected and so cannot be called to copy external objects. It is also not virtual, so you cannot override its implementation.

The ToString() Method

You've already encountered ToString() in Chapter 2, "C# Basics." It provides the most convenient way to get a quick string representation of an object.

For example:

 int i = -50;  string str = i.ToString(); // returns "-50" 

Here's another example:

 enum Colors {Red, Orange, Yellow}; // later on in code... Colors favoriteColor = Colors.Orange; string str = favoriteColor.ToString();     // returns "Orange" 

Object.ToString() is actually declared as virtual, and all these examples are taking advantage of the fact that its implementation in the C# predefined data types has been overridden for us in order to return correct string representations of those types. You might not think that the Colors enum counts as a predefined data type. It actually gets implemented as a struct derived from System.Enum, and System.Enum has a rather clever override of ToString() that deals with all the enums you define.

If you don't override ToString() in classes that you define, your classes will simply inherit the System.Object implementation — which displays the name of the class. If you want ToString() to return a string that contains information about the value of objects of your class, then you will need to override it. To illustrate this, the following example, Money, defines a very simple class, also called Money, which represent U.S. currency amounts. Money simply acts as a wrapper for the decimal class but supplies a ToString() method. Note that this method must be declared as override because it is replacing (overriding) the ToString() method supplied by Object. Chapter 4 discusses overriding in more detail. The complete code for this example is as follows. Note that it also illustrates use of properties to wrap fields:

 using System; namespace Wrox.ProCSharp.OOCSharp { class MainEntryPoint { static void Main(string[] args) { Money cash1 = new Money(); cash1.Amount = 40M; Console.WriteLine("cash1.ToString() returns: " + cash1.ToString()); Console.ReadLine(); } } class Money { private decimal amount; public decimal Amount { get { return amount; } set { amount = value; } } public override string ToString() { return "$" + Amount.ToString(); } } } 

This example is here just to illustrate syntactical features of C#. C# already has a predefined type to represent currency amounts, decimal, so in real life, you wouldn't write a class to duplicate this functionality unless you wanted to add various other methods to it. And in many cases, due to formatting requirements, you'd probably use the String.Format() method (which is covered in Chapter 8) rather than ToString() to display a currency string.

In the Main() method you first instantiate a Money object, then a BetterMoney object. In both cases you call ToString(). For the Money object, you'll pick up the Object version of this method that displays class information. For the BetterMoney object, you'll pick up your own override. Running this code gives the following results:

 StringRepresentations  cash1.ToString() returns: $40 




Professional C# 2005
Pro Visual C++ 2005 for C# Developers
ISBN: 1590596080
EAN: 2147483647
Year: 2005
Pages: 351
Authors: Dean C. Wills

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