2015-07-20 16 views
5

Tôi làm việc trên một dự án lớn trong C# .NET 4.0. Có một lớp tùy chỉnh được kế thừa từ lớp System.Net.Sockets.SocketAsyncEventArgs. Một cái gì đó như sau:Cách triển khai giao diện IDisposable trong một lớp được kế thừa từ SocketAsyncEventArgs

public class SocketTaskArgs : SocketAsyncEventArgs 
{ 
    public SocketTaskArgs() 
    { 
     Completed += someEventhHandler; 
    } 

    public void CleanUp() 
    { 
     Completed -= someEventhHandler; 
    } 

    /* 
     There is a lot of code here that is unimportant at the moment. 
    */ 
} 

Vì vậy, tôi muốn di chuyển nội dung của phương thức CleanUp() sang phương pháp Vứt bỏ (bool).

Lần đầu tiên, tôi đã kiểm tra mã nguồn của lớp cơ sở - SocketAsyncEventArgs (sử dụng Chuyển đến Định nghĩa để tôi thấy siêu dữ liệu là nguồn). Tôi phát hiện ra, lớp này triển khai giao diện IDisposable. Nice, tôi chỉ cần ghi đè lên phương thức Dispose (bool), phải không? (Xem IDisposable Interface on MSDN, phần "IDisposable và phân cấp thừa kế" để biết thêm chi tiết). Không có gì mới đối với tôi ... Thật không may, lớp SocketAsyncEventArgs được thực hiện như sau:

public class SocketAsyncEventArgs : EventArgs, IDisposable 
{ 
    public void Dispose(); 

    //some other stuff here 
} 

Điều đó có nghĩa, không có cách nào làm thế nào để ghi đè Dispose (bool) phương pháp, khi nó được thực hiện như tin thay của được bảo vệ ... Lý do cho điều này là gì?

Tiếp theo, tôi đọc về phương thức SocketAsyncEventArgs.Dispose() trên MSDN. Điều buồn cười là, nó có chứa các phần sau:

Thuyết thừa kế

Vứt bỏ có thể được gọi nhiều lần bởi đối tượng khác. Khi ghi đè Vứt bỏ (Boolean), hãy cẩn thận không tham chiếu các đối tượng đã được xử lý trước đây trong một cuộc gọi trước đó đến Vứt bỏ. Để biết thêm thông tin về cách triển khai Vứt bỏ (Boolean), xem Thực hiện Phương thức Vứt bỏ.

Chờ ... cái gì?

Khi trọng Dispose (Boolean) ...

Làm sao tôi phải ghi đè Dispose (Boolean)?

Cách được khuyến nghị để triển khai giao diện IDisposable trong trường hợp này là gì?

+1

Không riêng tư, không được thực hiện ở tất cả (xem http://referencesource.microsoft.com/System/net/System/Net/Sockets/Socket.cs.html#8877). Nó sử dụng trình hoàn thiện nhưng có vẻ như nó không thực sự được triển khai trong mẫu được đề xuất. –

+0

Có vẻ như 'Vứt bỏ' là công khai, không phải là' ảo'. –

+0

Bạn không được thừa kế từ lớp đó. Có thể bạn không thể thay đổi điều đó dễ dàng trong một dự án lớn hiện có. – usr

Trả lời

3

Có vẻ như không được bất cứ điều gì ngăn cản bạn từ việc thực hiện IDisposable trên lớp con quý vị, lấy ví dụ này:

public class DisposableParent : IDisposable 
{ 
    public void Dispose() 
    { 
     Console.WriteLine("The parent was disposed."); 
    } 
} 

public class DisposableChild : DisposableParent, IDisposable 
{ 
    public new void Dispose() 
    { 
     base.Dispose(); 
     Console.WriteLine("The child was disposed."); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     using (DisposableChild c = new DisposableChild()) { } 
     Console.ReadKey(true); 
    } 
} 

Cung cấp đầu ra sau đây:

Phụ huynh đã được xử lý.

Đứa trẻ đã được xử lý.

Trình biên dịch cảnh báo về ẩn dispose của lớp cha mẹ ở trẻ em, vì vậy sử dụng toán tử new được thoát khỏi cảnh báo rằng, chỉ cần đảm bảo để gọi lớp cơ sở Dispose từ lớp trẻ (và thực hiện nó đúng cách).

Các dispose cho đứa trẻ sẽ trở thành cái gì đó như:

public class DisposableChild : DisposableParent, IDisposable 
{ 
    private bool _disposed = false; 

    public new void Dispose() 
    { 
     Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (!_disposed) 
      { 
       base.Dispose(); 
       Console.WriteLine("The child was disposed."); 
       _disposed = true; 
      } 
     } 
    } 
} 

Và vâng, đây vẫn hoạt động nếu bạn làm điều gì đó như:

using (DisposableParent p = new DisposableChild()) 
{ 

} 

Nhưng một cái gì đó như thế này có thể phá vỡ nó:

public class Program 
{ 
    public static void Main() 
    { 
     DisposableChild c = new DisposableChild(); 
     DisposeOfIt(c); 

     Console.ReadKey(true); 
    } 

    public static void DisposeOfIt(DisposableParent p) 
    { 
     p.Dispose(); 
    } 
} 

Chỉ in ra rằng bố mẹ đã được xử lý. Vì vậy, nếu bạn sử dụng phương pháp này, bạn sẽ phải cẩn thận về việc kiểm soát tuổi thọ của các đối tượng của bạn.

+0

Cảm ơn câu trả lời. Tôi đồng ý với bạn, rằng tôi có thể thực hiện giao diện IDisposable trên lớp kế thừa của tôi. Đó thực sự là điều đầu tiên tôi nghĩ đến. Tôi chỉ tò mò nếu ai đó sẽ đến với người khác và có thể là một ý tưởng tốt hơn. Nếu không có gì tốt hơn trong tương lai gần, tôi sẽ đánh dấu câu trả lời của bạn là được chấp nhận. –

Các vấn đề liên quan