En mis clases implemento IDisposable de la siguiente manera:
public class User : IDisposable
{
public int id { get; protected set; }
public string name { get; protected set; }
public string pass { get; protected set; }
public User(int UserID)
{
id = UserID;
}
public User(string Username, string Password)
{
name = Username;
pass = Password;
}
// Other functions go here...
public void Dispose()
{
// Clear all property values that maybe have been set
// when the class was instantiated
id = 0;
name = String.Empty;
pass = String.Empty;
}
}
En VS2012, mi análisis de código dice implementar IDisposable correctamente, pero no estoy seguro de qué he hecho mal aquí.
El texto exacto es el siguiente:
CA1063 ID de implemento desechable correctamente Proporcione una implementación reemplazable de Dispose (bool) en 'Usuario' o marque el tipo como sellado. Una llamada a deshacerse (falso) solo debe limpiar los recursos nativos. Una llamada a la eliminación (verdadero) debe limpiar los recursos administrados y nativos. stman User.cs 10
Para referencia: CA1063: ID de implemento desechable correctamente
He leído esta página, pero me temo que realmente no entiendo lo que hay que hacer aquí.
Si alguien puede explicar en términos más generales cuál es el problema y / o cómo se debe implementar IDisposable, ¡eso realmente ayudará!
Dispose
?IDispoable
si tiene recursos no administrados de desechar (esto incluye los recursos no administrados que se envuelven (SqlConnection
,FileStream
, etc.). No es y no debe poner en prácticaIDisposable
si sólo han conseguido recursos como aquí. Esto es, la OMI, . un gran problema con el análisis de código es muy bueno en la comprobación tonta pequeñas reglas, pero no bueno en la comprobación de errores conceptuales.Respuestas:
Esta sería la implementación correcta, aunque no veo nada que deba disponer en el código que publicó. Solo necesita implementar
IDisposable
cuando:Nada en el código que publicó debe ser eliminado.
fuente
using(){ }
siempre que sea posible, pero para hacerlo, debe implementar IDisposable, por lo que, en general, prefiero acceder a una clase a través de usos, especialmente. si solo necesito la clase en una o dos funcionesusing
bloque cuando la clase implementa IDisposable . Si no necesita que una clase sea desechable, no la implemente. No sirve para nada.using
bloque tiende a ser atractiva más allá de laIDisposable
interfaz. Me imagino que ha habido más de unos pocos abusosIDisposable
solo con fines de alcance.GC.SuppressFinalize(this);
tiene sentido. Como señaló @mariozski, un finalizador ayudaría a garantizar queDispose
se llame en absoluto si la clase no se usa dentro de unusing
bloque.En primer lugar, no es necesario para "limpiar"
string
s yint
s - que será atendido de forma automática por el recolector de basura. Lo único que debe limpiarseDispose
son los recursos no administrados o los recursos administrados que se implementanIDisposable
.Sin embargo, suponiendo que esto sea solo un ejercicio de aprendizaje, la forma recomendada de implementar
IDisposable
es agregar una "captura de seguridad" para garantizar que los recursos no se eliminen dos veces:fuente
readonly
semántica)El siguiente ejemplo muestra las mejores prácticas generales para implementar la
IDisposable
interfaz. ReferenciaTenga en cuenta que necesita un destructor (finalizador) solo si tiene recursos no administrados en su clase. Y si agrega un destructor, debe suprimir Finalización en Dispose , de lo contrario hará que sus objetos residan en la memoria durante dos ciclos de basura (Nota: lea cómo funciona la Finalización ). A continuación se detallan todos los ejemplos anteriores.
fuente
IDisposable
existe para proporcionar un medio para que usted limpie los recursos no administrados que el recolector de basura no limpiará automáticamente.Todos los recursos que está "limpiando" son recursos administrados y, como tal, su
Dispose
método no está logrando nada. Tu clase no debería implementarseIDisposable
en absoluto. El recolector de basura se encargará de todos esos campos por sí solo.fuente
Debe usar el patrón desechable de esta manera:
fuente
SafeHandle
(y subtipos). En el caso de los recursos gestionados, la implementación de la eliminación adecuada se vuelve mucho más simple; puede recortar el código a una implementación simple delvoid Dispose()
método.No necesita hacer su
User
claseIDisposable
ya que la clase no adquiere ningún recurso no administrado (archivo, conexión de base de datos, etc.). Por lo general, marcamos las clases comoIDisposable
si tuvieran al menos unIDisposable
campo o propiedad. Al implementarIDisposable
, mejor ponlo según el esquema típico de Microsoft:fuente
Idisposable se implementa cuando se desea una recolección de basura determinista (confirmada).
Al crear y usar la clase Users, use el bloque "using" para evitar llamar explícitamente al método dispose:
El final del bloque de uso creado El objeto Usuarios se eliminará mediante la invocación implícita del método de eliminación.
fuente
Veo muchos ejemplos del patrón Microsoft Dispose, que es realmente un antipatrón. Como muchos han señalado, el código en la pregunta no requiere IDisposable en absoluto. Pero si va a implementarlo, no use el patrón de Microsoft. Una mejor respuesta sería seguir las sugerencias de este artículo:
https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About
La única otra cosa que probablemente sería útil es suprimir esa advertencia de análisis de código ... https://docs.microsoft.com/en-us/visualstudio/code-quality/in-source-suppression-overview?view=vs- 2017
fuente