Pourquoi FxCop génère-t-il l'erreur «Les types dont les champs à usage unique doivent être jetables devraient être jetables» sur une classe sans champs à usage unique?

StackOverflow https://stackoverflow.com/questions/1219086

  •  10-07-2019
  •  | 
  •  

Question

J'ai un objet LINQ auquel une méthode supplémentaire a été ajoutée. La classe n'a pas de propriétés ni de méthodes jetables, mais FxCop soulève l’erreur "Les types qui possèdent des champs à jeter doivent être jetables". et référençant cette classe.

J'ai réduit le code jusqu'à présent et je reçois toujours le message d'erreur:

partial class WikiPage
{
    public PagePermissionSet GetUserPermissions(Guid? userId) {
        using (WikiTomeDataContext context = new WikiTomeDataContext()) {
            var permissions =
                from wiki in context.Wikis
                from pageTag in context.VirtualWikiPageTags
                select new {};

            return null;
        }
    }
}

Cependant, si je supprime AUCUNE des clauses from, FxCop cesse de donner l'erreur:

partial class WikiPage
{
    public PagePermissionSet GetUserPermissions(Guid? userId) {
        using (WikiTomeDataContext context = new WikiTomeDataContext()) {
            var permissions =
                from pageTag in context.VirtualWikiPageTags
                select new {};

            return null;
        }
    }
}

Ou

partial class WikiPage
{
    public PagePermissionSet GetUserPermissions(Guid? userId) {
        using (WikiTomeDataContext context = new WikiTomeDataContext()) {
            var permissions =
                from wiki in context.Wikis
                select new {};

            return null;
        }
    }
}

PagePermissionSet n'est pas jetable.

Est-ce un faux positif? Ou le code LINQ génère-t-il en quelque sorte un champ disponible sur la classe? Si ce n’est pas un faux positif, FxCop recommande d’implémenter l’interface IDisposable, mais que ferais-je dans la méthode Dispose?

EDIT: L’erreur FxCop complète est:

  

" implémenter IDisposable sur 'WikiPage' car il   crée des membres des types IDisposable suivants:   'WikiTomeDataContext'. Si 'WikiPage' a déjà été   expédié, ajout de nouveaux membres qui implémentent IDisposable   à ce type est considéré comme un changement de rupture à l'existant   consommateurs. "

Éditer 2: C'est le code désassemblé qui génère l'erreur:

public PagePermissionSet GetUserPermissions(Guid? userId)
{
    using (WikiTomeDataContext context = new WikiTomeDataContext())
    {
        ParameterExpression CS
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
    // Fields
    public WikiTomeDataContext context;

    // Methods
    public <>c__DisplayClass1();
}
$0001; ParameterExpression CS<*>$0003; var permissions = context.Wikis.SelectMany(Expression.Lambda<Func<Wiki, IEnumerable<VirtualWikiPageTag>>>(Expression.Property(Expression.Constant(context), (MethodInfo) methodof(WikiTomeDataContext.get_VirtualWikiPageTags)), new ParameterExpression[] { CS<*>$0001 = Expression.Parameter(typeof(Wiki), "wiki") }), Expression.Lambda(Expression.New((ConstructorInfo) methodof(<>f__AnonymousType8..ctor), new Expression[0], new MethodInfo[0]), new ParameterExpression[] { CS<*>$0001 = Expression.Parameter(typeof(Wiki), "wiki"), CS<*>$0003 = Expression.Parameter(typeof(VirtualWikiPageTag), "pageTag") })); return null; } }

Éditer 3: Il semble qu'il y ait une classe de fermeture contenant une référence au DataContext. Voici son code désassemblé:

<*>
Était-ce utile?

La solution

Je suppose que les deux clauses From génèrent un appel à SelectMany avec une fermeture sur votre contexte de données. L'instance de la fermeture a un champ au datacontext qui provoque l'avertissement FxCop. Il n'y a pas de quoi s'inquiéter.

Il n'y a qu'une seule instance de votre contexte de données, que vous nettoyez via le bloc using. Comme la fermeture n’a pas de finaliseur, l’avertissement FxCop n’a aucune implication en termes de performances ou de sécurité.

Autres conseils

J'ai remarqué qu'il s'agit d'une classe partielle. Avez-vous vérifié l’autre fichier d’implémentation de la classe et vérifié s’il comporte un membre IDisposable qui n’est pas éliminé?

Je ne pense pas que la fermeture générée soit en cause ici. Les fermetures sont générées avec certains attributs qui devraient amener FxCop à ignorer des avertissements comme celui-ci.

MODIFIER

Une enquête plus poussée menée par le PO a montré que le problème était lié à la fermeture d’un champ identifiable.

Malheureusement, vous ne pouvez rien faire à ce sujet. Il n'y a aucun moyen de rendre la fermeture implémenter IDisposable. Événement si vous le pouvez, il n'y a aucun moyen d'appeler IDisposable sur l'instance de fermeture.

La meilleure façon d’aborder ce problème est de réécrire votre code de manière à ce qu’une valeur disponible ne soit pas saisie dans la fermeture. Les champs jetables doivent toujours être éliminés quand ils sont terminés et le capturer dans une fermeture vous empêche de le faire.

Si vous renvoyez une requête LINQ à partir de votre méthode, les utilisateurs procéderont à une itération des résultats à l'aide de foreach.

Lorsqu'un consommateur termine une boucle foreach, il appelle en interne dispose de la source IEnumerable (dans ce cas, votre requête LINQ). Ceci éliminera le WikiTomeDataContext.

Toutefois, si un consommateur appelle une méthode et retourne une requête LINQ mais ne répète jamais les résultats, il semblerait qu’il ne serait jamais possible d’énumérer une énumération (c’est-à-dire tant que le ramasse-miettes n'a pas nettoyé l’objet). Cela aurait pour conséquence que votre WikiTomeDataContext ne sera pas supprimé avant le ramassage des ordures.

Une façon de contourner ce problème consiste à appeler .ToArray sur le résultat de votre requête LINQ, appelez dispose sur votre contexte, puis renvoyez le tableau.

Votre code générant l'erreur utilise WikiDataContext.

Vos deux exemples qui ne génèrent pas d'erreur utilisent WikiTomeDataContext.

Peut-être y a-t-il une différence entre ces deux qui est à l'origine de l'erreur.

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