que method espaƱol clase abstracta c# pinvoke

method - virtual class c#



Implementando IDisposable en una clase sellada (4)

Del weblog de Joe Duffy :

Para las clases selladas, no es necesario seguir este patrón, lo que significa que simplemente debe implementar su Finalizer y Desechar con los métodos simples (es decir, ~ T () (Finalizar) y Desechar () en C #). Al elegir la última ruta, su código debe seguir las pautas a continuación con respecto a la implementación de la lógica de finalización y disposición.

Así que sí, deberías ser bueno.

Necesitas el finalizador como mencionó Mehrdad. Si desea evitarlo, puede echar un vistazo a SafeHandle . No tengo suficiente experiencia con P / Invoke para sugerir el uso correcto.

No creo que esta pregunta haya sido hecha antes. Estoy un poco confundido sobre la mejor manera de implementar IDisposable en una clase sellada, específicamente, una clase sellada que no hereda de una clase base. (Es decir, una "clase sellada pura" que es mi término inventado.)

Quizás algunos de ustedes estén de acuerdo conmigo en que las pautas para implementar IDisposable son muy confusas. Dicho esto, quiero saber que la forma en que pretendo implementar IDisposable es suficiente y segura.

Estoy haciendo un código P / Invoke que asigna un IntPtr través de Marshal.AllocHGlobal y, naturalmente, quiero deshacerme de la memoria no administrada que he creado. Así que estoy pensando en algo como esto

using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] public sealed class MemBlock : IDisposable { IntPtr ptr; int length; MemBlock(int size) { ptr = Marshal.AllocHGlobal(size); length = size; } public void Dispose() { if (ptr != IntPtr.Zero) { Marshal.FreeHGlobal(ptr); ptr = IntPtr.Zero; GC.SuppressFinalize(this); } } ~MemBlock() { Dispose(); } }

Supongo que debido a que MemBlock está completamente sellado y nunca se deriva de otra clase, no es necesario implementar un MemBlock virtual protected Dispose(bool disposing) .

Además, ¿el finalizador es estrictamente necesario? Todos los pensamientos son bienvenidos.


El finalizador es necesario como mecanismo de reserva para liberar recursos no administrados si olvidó llamar a Dispose .

No, no deberías declarar un método virtual en una clase sealed . No compilaría en absoluto. Además, no se recomienda declarar nuevos miembros protected en clases sealed .


No puedes declarar métodos virtuales en una clase sellada. También declarar miembros protegidos en una clase sellada le da una advertencia del compilador. Así que lo has implementado correctamente. Llamar a GC.SuppressFinalize (esto) desde el finalizador no es necesario por razones obvias, pero no puede dañar.

Tener un finalizador es esencial cuando se trata de recursos no administrados, ya que no se liberan automáticamente, tiene que hacerlo en el finalizador, se llama automáticamente después de que el objeto se haya recolectado como basura.


Una adición menor; en el caso general , un patrón común es tener un método de Dispose(bool disposing) , para que sepa si está en Dispose (donde hay más cosas disponibles) contra el finalizador (donde realmente no debe tocar ningún otro administrador conectado) objetos).

Por ejemplo:

public void Dispose() { Dispose(true); } ~MemBlock() { Dispose(false); } void Dispose(bool disposing) { // would be protected virtual if not sealed if(disposing) { // only run this logic when Dispose is called GC.SuppressFinalize(this); // and anything else that touches managed objects } if (ptr != IntPtr.Zero) { Marshal.FreeHGlobal(ptr); ptr = IntPtr.Zero; } }