16 避免創建不必要的對象
GC(垃圾回收)為我們管理內存,以一種比較有效的方式移除不使用的對象。但是不管怎樣分配和銷毀基於堆管理的對象
都會占用不少處理器時間,所以請不要加重GC的負擔,如下是一種比較糟糕的方式來分配GDI對象:
protected override void OnPaint(PaintEventArgs e) { // Bad. Created the same font every paint event. using (Font MyFont = new Font("Arial", 10.0f)) { e.Graphics.DrawString(DateTime.Now.ToString(), MyFont, Brushes.Black, new PointF(0, 0)); } base.OnPaint(e); }
private readonly Font myFont =new Font("Arial", 10.0f); protected override void OnPaint(PaintEventArgs e) { e.Graphics.DrawString(DateTime.Now.ToString(), myFont, Brushes.Black, new PointF(0, 0)); base.OnPaint(e); }
public class MyResourceHog : IDisposable { // Flag for already disposed private bool alreadyDisposed = false; // Implementation of IDisposable. // Call the virtual Dispose method. // Suppress Finalization. public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // Virtual Dispose method protected virtual void Dispose(bool isDisposing) { // Don't dispose more than once. if (alreadyDisposed) return; if (isDisposing) { // elided: free managed resources here. } // elided: free unmanaged resources here. // Set disposed flag: alreadyDisposed = true; } public void ExampleMethod() { if (alreadyDisposed) throw new ObjectDisposedException( "MyResourceHog", "Called Example Method on Disposed object"); // remainder elided. } }
public class DerivedResourceHog : MyResourceHog { // Have its own disposed flag. private bool disposed = false; protected override void Dispose(bool isDisposing) { // Don't dispose more than once. if (disposed) return; if (isDisposing) { // TODO: free managed resources here. } // TODO: free unmanaged resources here. // Let the base class free its resources. // Base class is responsible for calling // GC.SuppressFinalize( ) base.Dispose(isDisposing); // Set derived class disposed flag: disposed = true; } }
public class BadClass { // Store a reference to a global object: private static readonly ListfinalizedList = new List (); private string msg; public BadClass(string msg) { // cache the reference: msg = (string)msg.Clone(); } ~BadClass() { // Add this object to the list. // This object is reachable, no // longer garbage. It's Back! finalizedList.Add(this); } }
public struct Employee { // Properties elided public string Position { get; set; } public decimal CurrentPayAmount { get; set; } public void Pay(BankAccount b) { b.Balance += CurrentPayAmount; } }
public class Employee2 { // Properties elided public string Position { get; set; } public decimal CurrentPayAmount { get; set; } public virtual void Pay(BankAccount b) { b.Balance += CurrentPayAmount; } }
public enum Planet { // Default starts at 0 otherwise. Mercury = 1, Venus = 2, Earth = 3, Mars = 4, Jupiter = 5, Saturn = 6, Neptune = 7, Uranus = 8 // First edition included Pluto. } Planet sphere = new Planet();
public struct Address2 { // remaining details elided public string Line1 { get; private set; } public string Line2 { get; private set; } public string City { get; private set; } public string State { get; private set; } public int ZipCode { get; private set; } }
public Address2(string line1, string line2, string city, string state, int zipCode) : this() { Line1 = line1; Line2 = line2; City = city; ValidateState(state); State = state; ValidateZip(zipCode); ZipCode = zipCode; }
public struct Address3 { // remaining details elided public string Line1 { get { return Line1; } } private readonly string line1; public string Line2 { get { return line2; } } private readonly string line2; public string City { get { return city; } } private readonly string city; public string State { get { return state; } } private readonly string state; public int ZipCode { get { return zip; } } private readonly int zip; public Address3(string line1, string line2, string city, string state, int zipCode) : this() { this.line1 = line1; this.line2 = line2; this.city = city; ValidateState(state); this.state = state; ValidateZip(zipCode); this.zip = zipCode; } }
public struct PhoneList { private readonly Phone[] phones; public PhoneList(Phone[] ph) { phones = ph; } public IEnumerablePhones { get { return phones; } } } Phone[] phones = new Phone[10]; // initialize phones PhoneList pl = new PhoneList(phones); // Modify the phone list: // also modifies the internals of the (supposedly) // immutable object. phones[5] = Phone.GeneratePhoneNumber();
// Immutable: A copy is made at construction. public struct PhoneList2 { private readonly Phone[] phones; public PhoneList2(Phone[] ph) { phones = new Phone[ph.Length]; // Copies values because Phone is a value type. ph.CopyTo(phones, 0); } public IEnumerablePhones { get { return phones; } } } Phone[] phones2 = new Phone[10]; // initialize phones PhoneList p2 = new PhoneList(phones); // Modify the phone list: // Does not modify the copy in pl. phones2[5] = Phone.GeneratePhoneNumber();