站内搜索: 请输入搜索关键词
当前页面: 图书首页 > NET For Java Developers Migrating To C#

NET For Java Developers Migrating To C#

[ directory ] Previous Section Next Section

4.1 Object Creation

The cornerstone of any object-oriented programming language is the concept of an object. An object is a data structure that has methods and fields. Fields maintain the state of the object, and methods query or modify that state. Objects provide a convenient container for storing data. The number and type of lids on that container dictate the access control to the data. For example, an object that has only public methods is like an open container. Objects can get heavy (consume more memory) depending on the data they store. Objects are also used for abstracting the relationships among data.

In OOP languages such as C++, Java, and C#, objects are created using the new operator. An object is created in memory (usually the heap), and a reference to that object is obtained as shown here:

object o = new object();

The left side has the reference o, and it is assigned to the newly created object on the right side. Note that the reference o is merely a pointer to the actual object on the heap. You can use the reference to modify and query the state or data of the actual object by calling the object's method or setting its field:

o.field = "c#"
o.sayHello();

When you null an object, you merely set its reference to null. The keyword null is used in C++, Java, and C# to null objects. Note that null is not an object. Instead, it is a standardized reference to which references such as o can be set in order to null objects. Therefore, the following statement merely makes the reference o point to the null reference:

o = null;

After the reference is set to null, calling a method or accessing a field on that reference will give the classic NullPointerException (Java). This is obvious because there is no underlying object to which this reference is now pointing.

Note that a reference is a façade used to manipulate the actual object. References can be assigned to each other. Therefore, the following statement will assign an additional reference o1 to the object created earlier:

object o1 = o;

Assigning null to the reference o will not affect the reference o1. This latter reference will still keep pointing toward the actual object. When there are no such pointers (references) to that object, the object in memory is considered garbage, and the garbage collector (if one is supported by the language) will free up the memory consumed by that object.

In C# and Java, automatic garbage collection takes care of deallocating memory that was allocated using the new operator. Because object destruction is no longer an issue, programmers can now focus on proper class design and efficient object creation, thereby simplifying OOP. Still, you do need some knowledge of memory management and garbage collection to avoid mistakes that would hamper the garbage collection process. Section 4.8 discusses these issues in more detail.

4.1.1 The C# Equivalent of java.lang.Object

Both Java and C# have single-root object hierarchies. All objects always extend a standard root class. In Java this is the java.lang.Object class, and in C# it is the System.Object class. Table 4.1 compares System.Object and java.lang.Object and their approximate method equivalents.

If you are confused as to why the C# System.Object is referred to as object, it's because object is an alias for System.Object. To illustrate the various methods of System.Object, let's create a sample object as shown in Listing 4.1.

Table 4.1. The C# and Java Object Classes

System.Object (C#)

java.lang.Object (Java)

public object()

public Object()

public Equals(object o)

public equals(Object o)

public static Equals(object o1, object o2)

 

GetHashCode()

hashCode()

GetType

getClass()

ReferenceEquals (object a, object b)

 

ToString()

toString()

Finalize()

finalize()

MemberWiseClone()

 

Listing 4.1 Sample Object (C#)
  using System;
  public class Person {
    string name;
    public Person (string name) {
      this.name = name;
    }
    public override string ToString() {
      return this.name;
    }
    public override int GetHashCode() {
      return this.name.GetHashCode();
    }
    public override bool Equals(object o) {
      if (o != null && o.GetType().Equals(GetType())) {
        return this.name.Equals(((Person)o).name);
      }
      return false;
  }
    public Person copy() {
      return (Person)this.MemberwiseClone();
    }
}

Listing 4.2 runs some tests on the Person object.

Listing 4.2 Testing Person Objects (C#)
using System;
public class Test {
  public static void Main(string[] args) {

    Person p1 = new Person("chris");
    Person p2 = new Person("chris");
    Person p3 = p1;

    //Comparing p2 and p1;
    Console.WriteLine("Comparing p1 and p2");
    Console.WriteLine (p1.Equals(p2));
    Console.WriteLine (p1 == p2);
    Console.WriteLine (Person.ReferenceEquals(p1, p2));

    //Comparing p3 and p1;
    Console.WriteLine("Comparing p1 and p3");
    Console.WriteLine (p1.Equals(p3));
    Console.WriteLine (p1 == p3);
    Console.WriteLine (Person.ReferenceEquals(p1, p3));

    //Comparing p4 and p1;
    Console.WriteLine("Comparing p1 and p4");
    Person p4 = p1.copy();
    Console.WriteLine (p1.Equals(p4));
    Console.WriteLine (p1 == p4);
    Console.WriteLine (Person. ReferenceEquals (p1, p4));

    //Miscellaneous object methods
    Console.WriteLine(p1.GetType());
    Console.WriteLine(p1.ToString());
    Console.WriteLine(p1.GetHashCode());
  }
}

The output of Listing 4.2 is as follows:

Comparing p1 and p2
True
False
False
Comparing p1 and p3
True
True
True
Comparing p1 and p4
True
False
False
Miscellaneous object methods
Person
chris
177073830

The output will be obvious to most Java programmers because it is in tune with Java's notion of equality of objects. The following are the common ways to check for equality of objects:

  • The Equals method (public virtual bool Equals (object)). This code determines whether two Object instances are equal. This method is equivalent to the equals method of the java.lang.Object class. C# also provides a static version of the Equals method that takes two object instances as its argument.

  • The == operator. This determines whether the specified Object instances are the same instance. The == operator is similar to the same operator in Java, which compares the two references. So in the example, p3 and p1 are equal, but p1 and p2 are not equal because they point to two different object instances.

  • The ReferenceEquals method. This determines whether the specified Object instances are the same instance. The behavior is similar to that of the == operator. However, remember that operator overloading can sometimes change the meaning of the == operator, and hence it is safer to use the ReferenceEquals method to check for equality of references.

Note that in the Person class we created a copy() method that wraps the protected MemberwiseClone method. MemberwiseClone() is a protected method of the Object class that creates a shallow copy of the object. The method creates a new object in memory, and hence the == operator and the ReferenceEquals method return false for equality. The other methods of the System.Object class are similar in nature to those of the java.lang.Object class. The next section explores writing C# classes.

    [ directory ] Previous Section Next Section