}
}
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 usingkeyword. In the following example, the connobject 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 usingkeyword 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 statickeyword to class definitions. Consider the following FilesUtilclass 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 FilesUtilclass 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.Objectbase class (inheritance is discussed in the next chapter). This means that all classes contain the methods defined in the System.Objectclass.
All class definitions that do not inherit from other classes by default inherit directly from the System.Objectclass. The earlier Contactclass definition:
public class Contact
for example, is equivalent to:
public class Contact: Object
You can create an instance of the System.Objectclass if you want, but it is by itself not terribly useful:
Object o = new object();
The System.Objectclass 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.Objectclass 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.Objectalso 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 Contactclass, which implicitly inherits from the System.Objectclass:
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, c1and c2are identical in data member values, while c3is 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, c1and c2have the exact same values for the members, so why does the Equals()method return Falsein this case? It turns out that the Equals()method must be overridden in the Contactclass definition. This is because by itself, the System.Objectclass 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.
Читать дальше