Question

Je reçois un avertissement quand je lance un code par l'utilitaire d'analyse du code de Visual Studio que je ne suis pas sûr de savoir comment résoudre. Peut-être que quelqu'un ici a rencontré un problème similaire, résolu, et est prêt à partager leur vision.

Je suis programmation d'une cellule peinte sur mesure utilisé dans un contrôle DataGridView. Le code ressemble:

public class DataGridViewMyCustomColumn : DataGridViewColumn
{
    public DataGridViewMyCustomColumn() : base(new DataGridViewMyCustomCell())
    {
    }

Il génère l'avertissement suivant:

CA2000: Microsoft.Reliability: Dans la méthode 'DataGridViewMyCustomColumn.DataGridViewMyCustomColumn ()' appel System.IDisposable.Dispose sur l'objet «nouveau DataGridViewMyCustomCell () avant que toutes les références à celui-ci sont hors de portée <. / p>

Je comprends qu'il me garde met en œuvre DataGridViewMyCustomCell (ou une classe qui hérite de) l'interface IDisposable et la méthode Dispose () doit être appelé à nettoyer les ressources revendiquées par DataGridViewMyCustomCell quand il n'est plus.

Les exemples que j'ai vu sur Internet suggérer un bloc en utilisant la portée la durée de vie de l'objet et que le système de disposer automatiquement, mais la base ne soit pas reconnue lors de son déplacement dans le corps du constructeur, donc je ne peux pas écrire un bloc à l'aide autour d'elle ... que je ne suis pas sûr que je veux faire de toute façon, puisque ce ne serait pas le instruire de l'exécution pour libérer l'objet qui pourrait encore être utilisé plus tard dans la classe de base?

Ma question est donc le code correct comme cela est? Ou, comment pourrait-il être refactorisé pour résoudre l'avertissement? Je ne veux pas supprimer l'avertissement à moins qu'il soit vraiment approprié de le faire.

Était-ce utile?

La solution

Si vous utilisez Visual Studio 2010 puis CA2000 est complètement cassé. Il peut également être cassé dans d'autres versions de FxCop (Code analyse a.k.a.), mais VS2010 est le seul que je peux en témoigner. Notre base de code donne des avertissements CA2000 pour le code comme ça ...

internal static class ConnectionManager 
{
    public static SqlConnection CreateConnection()
    {
         return new SqlConnection("our connection string");
    }
}

... indiquant que la connexion ne soit pas disposé avant qu'il ne sort de la portée du procédé. Eh bien, oui, cela est vrai, mais ce n'est pas hors de portée pour l'application comme il est revenu à un appelant - qui est le point de l'ensemble de la méthode! De la même façon, votre argument constructeur ne va pas hors de portée, mais est passé à la classe de base, il est donc un faux positif de la règle plutôt que d'un problème réel.

Cette habitude d'être une règle utile, mais maintenant tout ce que vous pouvez vraiment faire est de désactiver jusqu'à ce qu'ils le réparer. Ce qui est regrettable, parce que les (très peu) positifs réels sont des choses qui doivent être fixés.

Autres conseils

Il n'y a pas de moyen sûr et élégant d'avoir un constructeur chaîné passer un nouvel objet IDisposable au constructeur de base, étant donné que vous constatez qu'il est impossible d'envelopper l'appel du constructeur enchaînée dans une sorte de bloc try finally. Il y a une approche qui est sûr, mais il est à peine élégante: définir une méthode utilitaire quelque chose comme:

internal static TV storeAndReturn<TR,TV>(ref TR dest, TV value) where TV:TR
{ 
  dest = value; return value;
}

Avoir le look constructeur quelque chose comme:

protected DataGridViewMyCustomColumn(ref IDisposable cleaner) : 
   base(storeAndReturn(ref cleaner, new DataGridViewMyCustomCell()))
{
}

Code qui a besoin d'un nouvel objet devrait alors appeler une méthode d'usine statique publique qui appelle le constructeur approprié dans un try / bloc finally dont la principale serait nulle sur cleaner juste avant qu'il a terminé, et dont le bloc finally appellerait Dispose sur cleaner si elle est non nulle. A condition que chaque sous-classe définit une méthode de fabrication similaire, cette approche fera en sorte que le nouvel objet IDisposable va se disposés même si une exception se produit entre temps, il est créé et le temps l'objet d'encapsulation est exposé au code client. Le modèle est laid, mais je ne suis pas sûr plus gentil autre modèle assurerait la décision correcte.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top