11
votes

Renvoie la variable utilisée pour utiliser à l'intérieur de l'utilisation C #

Je retourne la variable que je crée dans une instruction à l'aide de la déclaration à l'aide de l'instruction Utilisation (sonne drôle):

public DataTable foo ()
{
    using (DataTable properties = new DataTable())
    {
       // do something
       return properties;
    }
}


1 commentaires

Quoi qu'il en soit, c'est juste un mauvais design et devrait être retravaillé.


7 Réponses :


12
votes

Si vous voulez le retourner, vous ne pouvez pas l'envelopper dans un à l'aide de la déclaration , car une fois que vous avez quitté les accolades, il est hors de portée et est éliminé.

vous aurez Pour l'instancier comme ceci: xxx

et appelez jetez () dessus ultérieurement.


1 commentaires

Il se sent comme foo () == gesteuseDatable () et le bloc à l'aide du bloc doit être ce qui appelle cette fonction.



3
votes

Oui. Pourquoi utilisez-vous le mot-clé à l'aide de quelque chose que vous ne voulez pas disposer à la fin du bloc de code?

Le but du mot à l'aide de est de disposer de l'objet.

http://msdn.microsoft.com/en-us/library /yh598w02.aspx


0 commentaires

10
votes

Oui, il le disposera - puis le retournera. C'est presque toujours une mauvaise chose à faire.

En fait pour DataTable , Dispose ne fait presque jamais rien (l'exception étant si elle est reprise quelque part, IIRC), mais c'est toujours une idée généralement mauvaise. Normalement, vous devez considérer les objets disposés comme inutilisables.


3 commentaires

Donc, quel serait le modèle correct pour renvoyer un objet iDisposable à partir d'une méthode sans déclenchement de l'avertissement CA2000?


@Jhonny: Je ne sais pas, pour être honnête - je n'ai pas utilisé d'analyse de code comme celui-ci. Je m'attendrais à ce qu'il y aurait un moyen de supprimer l'avertissement.


@ Jhonnyd.cano-restware - Si vous allez instancier et retourner des choses isisposables, vous devez les disposer explicitement dans votre code. Votre analyse de code "devrait" reprendre que vous le disposez manuellement.



2
votes

Le point d'un bloc d'utilisation consiste à créer une portée artificielle d'une valeur / objet. Lorsque l'utilisation du bloc est terminée, l'objet est nettoyé car il n'est plus nécessaire. Si vous souhaitez vraiment retourner l'objet que vous créez, ce n'est pas un cas où vous souhaitez utiliser l'utilisation.

Cela fonctionnera simplement bien. P>

public DataTable foo ()
{
    DataTable properties = new DataTable();
    // do something
    return properties;
}


0 commentaires

1
votes

Votre code à l'aide du mot clé se développe à:

{
    DataTable properties = new DataTable();
    try
    {
        //do something
        return properties;
    }
    finally
    {
        if(properties != null)
        {
            ((IDisposable)properties).Dispose();
        }
    }
}


0 commentaires

7
votes

soi-disant, il s'agit du motif d'une méthode d'usine qui crée un objet jetable. Mais, j'ai encore vu une analyse de code se plaint de cela aussi:

        Wrapper tempWrapper = null;
        Wrapper wrapper = null;

        try
        {
            tempWrapper = new Wrapper(callback);
            Initialize(tempWrapper);

            wrapper = tempWrapper;
            tempWrapper = null;
        }
        finally
        {
            if (tempWrapper != null)
                tempWrapper.Dispose();
        }

        return wrapper;


3 commentaires

N'est-ce pas essentiellement équivalent à un bloc de capture? Pourquoi n'écrirais-tu pas wrapper x = null; essayez {...} attraper {if (x! = null) x.dispose (); } . L'intention n'est pas seulement 100% plus évidente, mais évite la variable de température inutile et le nettoyage manuel.


Je ne suis pas en désaccord. Mais je viens de regarder ça récemment moi-même, pas parce que je craignais de disposer de l'objet sur l'échec, mais parce que j'essayais de trouver le modèle de code qui éliminerait l'avertissement CA2000 sans que je doive la supprimer via l'attribut. Le processus d'analyse de code vérifie spécifiquement si l'objet est disposé dans un blocage enfin en raison de la nature de la règle appliquée. Je percevoir que cette question est vraiment à propos de CA2000, pas sur la disposition d'objets.


@Juliet: La déclaration manque à une réthrow, et même avec une retirante, la sémantique n'est pas la même chose que de ne pas avoir une prise. Entre autres choses, si le block contient aux appels à une méthode bla qui pourrait provoquer une exception, Catch-and-Rethow causera la trace de la pile de montrer le numéro de ligne de la réthrosse plutôt que l'appel à bla (la trace de la pile dans bla sera correcte, mais le numéro de ligne de l'appel ne sera pas).



0
votes

Les autres réponses sont correctes: dès que vous quittez l'utilisation du bloc, votre objet est disposé. L'utilisation de bloc est idéale pour s'assurer qu'un objet est éliminé de manière opportune, donc si vous ne voulez pas compter sur les consommateurs de votre fonction pour vous rappeler de disposer de l'objet plus tard, vous pouvez essayer quelque chose comme ceci:

var user = GetNewUserInfo();
UsingDataContext(c => c.UserSet.Add(user));


0 commentaires