}
}
You can now manually dispose of unmanaged resources by calling the Dispose()
method directly:
Contact c1 = new Contact(); //...
//---done with c1 and want to dispose it---
c1.Dispose();
There is now a call to the Dispose()
method within the destructor, so you must make sure that the code in that method is safe to be called multiple times — manually by the user and also automatically by the garbage collector.
The Using Statement
C# provides a convenient syntax for automatically calling the Dispose()
method, using the using
keyword. In the following example, the conn
object is only valid within the using block and will be disposed automatically after the execution of the block.
using System.Data.SqlClient;
...
using (SqlConnection conn = new SqlConnection()) {
conn.ConnectionString = "...";
//...
}
Using the using
keyword is a good way for you to ensure that resources (especially COM objects and unmanaged code, which will not be unloaded automatically by the garbage collector in the CLR) are properly disposed of once they are no longer needed.
You can also apply the static
keyword to class definitions. Consider the following FilesUtil
class definition:
public class FilesUtil {
public static string ReadFile(string Filename) {
//---implementation---
return "file content...";
}
public static void WriteFile(string Filename, string content) {
//---implementation---
}
}
Within this class are two static methods — ReadFile()
and WriteFile()
. Because this class contains only static methods, creating an instance of this class is not very useful, as Figure 4-4 shows.
Figure 4-4
As shown in Figure 4-4, an instance of the FilesUtil
class does not expose any of the static methods defined within it. Hence, if a class contains nothing except static methods and properties, you can simply declare the class as static, like this:
public static class FilesUtil {
public static string ReadFile(string Filename) {
//---implementation---
return "file content...";
}
public static void WriteFile(string Filename, string content) {
//---implementation---
}
}
The following statements show how to use the static class:
//---this is not allowed for static classes---
FilesUtil f = new FilesUtil();
//---these are OK---
Console.WriteLine(FilesUtil.ReadFile(@"C:\TextFile.txt"));
FilesUtil.WriteFile(@"C:\TextFile.txt", "Some text content to be written");
Use static classes when the methods in a class are not associated with a particular object. You need not create an instance of the static class before you can use it.
In C#, all classes inherit from the System.Object
base class (inheritance is discussed in the next chapter). This means that all classes contain the methods defined in the System.Object
class.
All class definitions that do not inherit from other classes by default inherit directly from the System.Object
class. The earlier Contact
class definition:
public class Contact
for example, is equivalent to:
public class Contact: Object
You can create an instance of the System.Object
class if you want, but it is by itself not terribly useful:
Object o = new object();
The System.Object
class exposes four instance methods (see Figure 4-5):
□ Equals()
— Checks whether the value of the current object is equal to that of another object. By default, the Equals()
method checks for reference equality (that is, if two objects are pointing to the same object). You should override this method for your class.
□ GetHashCode()
— Returns a hash code for the class. The GetHashCode()
method is suitable for use in hashing algorithms and data structures, such as a hash table. There will be more about hashing in Chapter 11
□ GetType()
— Returns the type of the current object
□ ToString()
— Returns the string representation of an object
Figure 4-5
In addition, the System.Object
class also has two static methods (see Figure 4-6):
□ Equals()
— Returns true if the two objects are equal (see next section for more details)
□ ReferenceEquals()
— Returns true if two objects are from the same instance
Figure 4-6
All classes that inherit from System.Object
also inherit all the four instance methods, a couple of which you will learn in more details in the following sections.
Consider the following three instances of the Contact
class, which implicitly inherits from the System.Object
class:
Contact c1 = new Contact() {
ID = 1234,
FirstName = "Wei-Meng",
LastName = "Lee",
Email = "weimenglee@learn2develop.net"
};
Contact c2 = new Contact() {
ID = 1234,
FirstName = "Wei-Meng",
LastName = "Lee",
Email = "weimenglee@learn2develop.net"
};
Contact c3 = new Contact() {
ID = 4321,
FirstName = "Lee",
LastName = "Wei-Meng",
Email = "weimenglee@gmail.com"
};
As you can see, c1
and c2
are identical in data member values, while c3
is different. Now, let's use the following statements to see how the Equals()
and ReferenceEquals()
methods work:
Console.WriteLine(c1.Equals(c2)); //---False---
Console.WriteLine(c1.Equals(c3)); //---False---
c3 = c1;
Console.WriteLine(c1.Equals(c3)); //---True---
Console.WriteLine(Object.ReferenceEquals(c1, c2)); //---False---
Console.WriteLine(Object.ReferenceEquals(c1, c3)); //---True---
The first statement might be a little surprising to you; did I not just mention that you can use the Equals()
method to test for value equality?
Console.WriteLine(c1.Equals(c2)); //---False---
In this case, c1
and c2
have the exact same values for the members, so why does the Equals()
method return False
in this case? It turns out that the Equals()
method must be overridden in the Contact
class definition. This is because by itself, the System.Object
class does not know how to test for the equality of your custom class; the Equals()
method is a virtual method and needs to be overridden in derived classes. By default, the Equals()
method tests for reference equality.
Читать дальше