84 votes

à l'aide de déclaration vs essayez enfin

J'ai un tas de propriétés qui je vais utiliser la lecture/écriture des verrous sur les. Je peux les mettre en œuvre, soit avec un essai enfin ou à l'aide de la clause. Dans le try enfin, je voudrais acquérir le verrou avant de l'essayer, et ralease dans le enfin. En utilisant l'article, je voudrais créer une classe qui acquiert le verrou dans son constructeur, et les rejets dans sa méthode dispose. Je suis à l'aide de lire/écrire les verrous dans beaucoup d'endroits, donc j'ai été à la recherche de moyens qui pourraient être plus concis que d'essayer enfin. Je suis intéressé à entendre quelques idées sur le pourquoi d'une façon peut-être pas recommandé, ou pourquoi on pourrait être meilleur qu'un autre.

Méthode 1 (essayez enfin):

static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
    get 
    {
        rwlMyLock_m .AcquireReaderLock(0);
        try
        {
            return dtMyDateTime_m
        }
        finally
        {
            rwlMyLock_m .ReleaseReaderLock();
        }
    }
    set 
    { 
        rwlMyLock_m .AcquireWriterLock(0);
        try
        {
            dtMyDateTime_m = value;
        }
        finally
        {
            rwlMyLock_m .ReleaseWriterLock();
        }
    }
}

Méthode 2:

static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
    get
    {
        using (new ReadLock(rwlMyLock_m))
        {
            return dtMyDateTime_m;
        }
    }
    set
    {
        using (new WriteLock(rwlMyLock_m))
        {
            dtMyDateTime_m = value;
        }
    }
}

public class ReadLock : IDisposable
{
    private ReaderWriterLock rwl;
    public ReadLock(ReaderWriterLock rwl)
    {
        this.rwl = rwl;
        rwl.AcquireReaderLock(0);
    }

    public void Dispose()
    {
        rwl.ReleaseReaderLock();
    }
}
public class WriteLock : IDisposable
{
    private ReaderWriterLock rwl;
    public WriteLock(ReaderWriterLock rwl)
    {
        this.rwl = rwl;
        rwl.AcquireWriterLock(0);
    }

    public void Dispose()
    {
        rwl.ReleaseWriterLock();
    }
}

97voto

chakrit Points 29562

À partir de MSDN, à l'aide de Déclaration (Référence C#)

L'instruction using assure que Jeter, même si une exception se produit lors de l'appel de méthodes sur l'objet. Vous pouvez obtenir le même résultat en mettant l'objet à l'intérieur d'un bloc try et puis l'appel de la Jeter dans un bloc finally; en fait, c'est la façon dont l'instruction à l'aide qui se traduit par le compilateur. L'exemple de code plus tôt s'étend dans le code suivant au moment de la compilation (note supplémentaires des accolades pour créer de la portée limitée de l'objet):

{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}

Donc, fondamentalement, c'est le même code mais avec une belle automatique null-un contrôle et d'une étendue supplémentaire pour votre variable. La documentation indique également qu'il "s'assure de la bonne utilisation de IDisposable objet" de sorte que vous pourriez aussi bien est encore meilleur cadre de soutien pour tous les obscurs cas à l'avenir.

Alors, allez à l'option 2.

Avoir la variable à l'intérieur d'un champ d'application qui se termine immédiatement après il n'est plus nécessaire est également un plus.

12voto

Rob Walker Points 25840

Je préfère largement la deuxième méthode. Il est plus concis au point d'utilisation, et moins sujette aux erreurs.

Dans le premier cas, quelqu'un à éditer le code doit être prudent de ne pas insérer quoi que ce soit entre les Acquérir(Lecture|Écriture)de blocage d'appels et de les essayer.

(À l'aide d'un verrou lecture/écriture sur les propriétés individuelles, comme c'est généralement les excès de si. Ils sont mieux appliquées à un niveau beaucoup plus élevé. Un simple verrou il suffit souvent ici, puisque la possibilité de contention est vraisemblablement très faible étant donné le temps que le verrou est maintenu et l'acquisition d'un verrou lecture/écriture est plus cher qu'un simple verrou).

9voto

Steven A. Lowe Points 40596

envisager la possibilité que les deux solutions sont mauvais parce qu' ils masquent des exceptions

un essai sans prise doit évidemment être une mauvaise idée; voir msdn pour lesquelles l'instruction à l'aide est de même dangereux

notez aussi le MS maintenant recommande ReaderWriterLockSlim au lieu de ReaderWriterLock

enfin, notez que le MS exemples d'utilisation de deux blocs try-catch pour éviter ces problèmes, par exemple

try
{
    try
    {
         //readerwriterlock stuff
    }
    finally
    {
         //release lock
    }
 }
 catch(Exception ex)
 {
    //do something with exception
 }

un simple, cohérente, nettoyer la solution est un bon objectif, mais en supposant que vous ne pouvez pas utiliser de verrouillage(ce){return mydateetc;} vous pourriez reconsidérer l'approche; avec plus d'info je suis sûr que peut aider ;-)

5voto

Rob Williams Points 6316

Personnellement, j'utilise le C# "à l'aide de la" déclaration aussi souvent que possible, mais il y a quelques choses que je fais avec elle afin d'éviter les problèmes mentionnés. Pour illustrer:

void doSomething()
{
    using (CustomResource aResource = new CustomResource())
    {
        using (CustomThingy aThingy = new CustomThingy(aResource))
        {
            doSomething(aThingy);
        }
    }
}

void doSomething(CustomThingy theThingy)
{
    try
    {
        // play with theThingy, which might result in exceptions
    }
    catch (SomeException aException)
    {
        // resolve aException somehow
    }
}

Notez que j'ai séparé les "aide" énoncé dans l'une et l'utilisation de l'objet(s) en une autre méthode avec un "essayer"/"attraper" à bloc. J'ai peut imbriquer plusieurs "l'aide" de ce type de déclarations pour les objets connexes (je vais parfois trois ou quatre dans les profondeurs de mon code de production).

Dans mon Dispose() méthodes pour ces personnalisées IDisposable classes, j'attrape les exceptions (mais PAS des erreurs) et de la session (à l'aide de Log4net). Je n'ai jamais rencontré une situation où l'une de ces hypothèses pourraient avoir une incidence sur mon traitement. Les erreurs potentielles, comme d'habitude, sont autorisés à se propager jusqu'à la pile d'appel et généralement terminer le traitement avec un message approprié (l'erreur et la trace de la pile) connecté.

Si, j'ai rencontré une situation où une importante exception peut se produire pendant l' Dispose(),, je voudrais refonte de cette situation. Franchement, je doute que va jamais arriver.

Pendant ce temps, le champ d'application et de nettoyage des avantages de "l'aide" de faire l'un de mes plus favori C# caractéristiques. En passant, je travaille en Java, C#, Python et que mon la primaire langues, avec beaucoup d'autres jetés ici et là, et de "l'aide" est l'un de mes préférés de la langue dispose de tous, parce que c'est une pratique, tous les jours de bête de somme.

4voto

Will Points 76760

J'aime la 3ème option

private object _myDateTimeLock = new object();
private DateTime _myDateTime;

public DateTime MyDateTime{
  get{
    lock(_myDateTimeLock){return _myDateTime;}
  }
  set{
    lock(_myDateTimeLock){_myDateTime = value;}
  }
}

De vos deux options, la seconde option est la plus propre et la plus facile de comprendre ce qu'il se passe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X