2009-10-08 16 views
0

Le RAII s'applique-t-il au C#? Plus précisément, lors de la déclaration de variables, existe-t-il une différence interne entre déclarer une variable utilisée dans différentes méthodes au niveau de la classe (ce que je fais mais pas thread safe) ou à chaque niveau de méthode où elle est déclarée/instanciée plusieurs fois est nécessaire, puis sort de la portée?Déclaration des variables réutilisées au niveau de la classe ou de la méthode lorsqu'elles sont requises

Par exemple, un objet SqlConnection peut être utilisé dans différentes méthodes d'une classe - devrait-il être déclaré au niveau supérieur/classe ou séparément dans chaque méthode?

class Test 
{ 
    SqlConnection conn; 
    .... 

instanciés dans un bloc à l'aide et est hors de portée dans plusieurs méthodes différentes.

Ou ...

public void A() 
{ 
    SqlConnection conn = new SqlConnection(); 
} 

Et de même pour plusieurs méthodes.

Merci

Répondre

2

Il doit être déclaré au bon endroit.

Si ce n'est pas réellement partagé entre les méthodes, il devrait être interne à la méthode - indépendamment du fait que 20 méthodes nécessitent des objets de connexion. Vous ne faites pas une seule variable lp dans votre classe juste parce que plusieurs méthodes doivent faire des boucles (ce n'est pas FORTRAN).

Et oui, il y a une différence totale en interne.

0

RAII s'applique différemment pour les langages gérés en mémoire tels que C#. L'article Wikipédia s'applique principalement à C++. La section Java est plus appropriée. Pour les ressources non gérées en C#, consultez le Dispose Pattern.

EDIT: SqlConnection implémente IDisposable, vous aurez envie de faire une des opérations suivantes:

  • Faites-en local et en disposer immédiatement d'un bloc à l'aide
  • Faites un champ de votre classe et mettre en œuvre le modèle Dispose votre classe
  • Passer une instance de votre classe et faire l'appelant responsable de l'élimination de celui-ci
  • une autre technique où une certaine classe/méthode est responsable de l'élimination de celui-ci
0

Il existe des différences: (en règle générale, déclarer où vous en avez besoin)

Pour les types de référence: lorsque la variable conn est hors de portée, la connexion sql est admissible à la collecte des ordures. Ainsi, dans le premier exemple, si vous ne disposez pas de conn/null lorsque vous avez terminé, vous conserverez votre instance de connexion, même si vous ne l'utilisez pas. Pour les types de valeurs: (ints, structs, etc.) la variable locale est allouée sur la pile, mais si vous la déclarez au niveau de la classe, elle utilise la mémoire heap.

Vous pourriez peut réduire l'efficacité du collecteur des ordures - si vous allouez un grand nombre d'objets au niveau de la classe, et les conserver plus longtemps que vous en avez besoin, ils sont plus susceptibles de le faire à la génération 2 Vous pouvez (de façon décisive) être dans une position où vos collections (peu coûteuses) ne satisfont pas, et l'exécution commence à effectuer plus de collections de gen 2 (cher)

Au-delà, c'est juste une bonne pratique de les délayer là où vous les utilisez. Cela rend le code plus compréhensible et réduit le potentiel d'erreurs causées par les effets secondaires.

+0

Alors, en réalité, c'est à la sémantique (par exemple, utiliser le tas quand le type de valeur est déclaré au niveau de la classe)? Je peux annuler l'effet knockon pour le GC si je déclare au niveau de la classe, mais ensuite disposer/ré-instancier la même variable? Idéalement, la meilleure approche semble fixer les objets au niveau de la classe lorsqu'ils sont utilisés dans toute la classe, puis les éliminer le plus tôt possible. – dotnetdev

+0

Cela dépend: si vous déclarez un int, alors vous utilisez vraiment la mémoire pour cet int. Si vous déclarez une référence d'objet, votre référence utilise la mémoire (l'instance d'objet entière n'est pas allouée, mais la référence 32/64 bits est). Au-delà, je pense qu'il vaut mieux déclarer localement que si l'objet appartient réellement à l'état de votre objet. Dans votre exemple de connexion, si vous allez plusieurs fois l'utiliser, puis l'annuler à chaque appel de méthode, je dirais que c'est une variable locale (méthode). – JMarsch

+0

Oh, et juste pour être clair, si vous déclarez une variable de type référence dans votre corps de méthode (comme votre sqlconnection), puis que vous remettez en place l'objet et l'assignez à la variable locale, l'objet vit sur le tas, la référence (sorte de pointeur, mais pas vraiment) vit sur la pile. – JMarsch

Questions connexes