L'utilisateur kokos a répondu à la merveilleuse question Caractéristiques cachées de C # en mentionnant le using
mot - clé. Pourriez-vous préciser ceci? Quelles sont les utilisations de using
?
L'utilisateur kokos a répondu à la merveilleuse question Caractéristiques cachées de C # en mentionnant le using
mot - clé. Pourriez-vous préciser ceci? Quelles sont les utilisations de using
?
Réponses:
La raison de l' using
instruction est de s'assurer que l'objet est supprimé dès qu'il sort de la portée, et il ne nécessite pas de code explicite pour garantir que cela se produit.
Comme dans Comprendre l'instruction 'using' en C # (codeproject) et Utiliser des objets qui implémentent IDisposable (microsoft) , le compilateur C # convertit
using (MyResource myRes = new MyResource())
{
myRes.DoSomething();
}
à
{ // Limits scope of myRes
MyResource myRes= new MyResource();
try
{
myRes.DoSomething();
}
finally
{
// Check for a null resource.
if (myRes != null)
// Call the object's Dispose method.
((IDisposable)myRes).Dispose();
}
}
C # 8 introduit une nouvelle syntaxe, nommée "à l' aide de déclarations ":
Une déclaration using est une déclaration de variable précédée du mot clé using. Il indique au compilateur que la variable déclarée doit être supprimée à la fin de la portée englobante.
Ainsi, le code équivalent ci-dessus serait:
using var myRes = new MyResource();
myRes.DoSomething();
Et lorsque le contrôle quitte la portée contenante (généralement une méthode, mais il peut également s'agir d'un bloc de code), myRes
il sera supprimé.
using
s'assure que cela Dispose
est appelé une fois que vous avez fini avec l'objet.
MyRessource
s'agit d'une structure. Il n'y a évidemment pas de test de nullité, mais pas de boxe non plus IDisposable
. Un appel virtuel contraint est émis.
using
, la variable construite à l'intérieur est en lecture seule. Il n'y a aucun moyen d'y parvenir pour les variables locales sans l' using
instruction.
Puisque beaucoup de gens le font encore:
using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
//code
}
Je suppose que beaucoup de gens ne savent toujours pas que vous pouvez faire:
using (System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader("")) {
//code
}
Des choses comme ça:
using (var conn = new SqlConnection("connection string"))
{
conn.Open();
// Execute SQL statement here on the connection you created
}
Cela SqlConnection
sera fermé sans avoir besoin d'appeler explicitement la .Close()
fonction, et cela se produira même si une exception est levée , sans avoir besoin d'un try
/ catch
/ finally
.
return
au milieu du using
bloc.
utilisant, dans le sens de
using (var foo = new Bar())
{
Baz();
}
Est en fait un raccourci pour un bloc try / finally. Il est équivalent au code:
var foo = new Bar();
try
{
Baz();
}
finally
{
foo.Dispose();
}
Vous noterez, bien sûr, que le premier extrait est beaucoup plus concis que le second et également qu'il existe de nombreuses sortes de choses que vous voudrez peut-être faire comme nettoyage même si une exception est levée. Pour cette raison, nous avons trouvé une classe que nous appelons Scope qui vous permet d'exécuter du code arbitraire dans la méthode Dispose. Ainsi, par exemple, si vous aviez une propriété appelée IsWorking que vous vouliez toujours définir sur false après avoir tenté d'effectuer une opération, vous le feriez comme ceci:
using (new Scope(() => IsWorking = false))
{
IsWorking = true;
MundaneYetDangerousWork();
}
Vous pouvez en savoir plus sur notre solution et comment nous l'avons dérivée ici .
La documentation Microsoft indique que l' utilisation a une double fonction ( https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx ), à la fois comme directive et dans les instructions . En tant qu'instruction , comme cela a été souligné ici dans d'autres réponses, le mot clé est essentiellement du sucre syntaxique pour déterminer une portée pour disposer d'un objet IDisposable . En tant que directive , il est couramment utilisé pour importer des espaces de noms et des types. Également en tant que directive, vous pouvez créer des alias pour les espaces de noms et les types, comme indiqué dans le livre "C # 5.0 en bref: le guide définitif" ( http://www.amazon.com/5-0-Nutshell-The- Definitive-Reference-ebook / dp / B008E6I1K8), par Joseph et Ben Albahari. Un exemple:
namespace HelloWorld
{
using AppFunc = Func<IDictionary<DateTime, string>, List<string>>;
public class Startup
{
public static AppFunc OrderEvents()
{
AppFunc appFunc = (IDictionary<DateTime, string> events) =>
{
if ((events != null) && (events.Count > 0))
{
List<string> result = events.OrderBy(ev => ev.Key)
.Select(ev => ev.Value)
.ToList();
return result;
}
throw new ArgumentException("Event dictionary is null or empty.");
};
return appFunc;
}
}
}
C'est quelque chose à adopter sagement, car l'abus de cette pratique peut nuire à la clarté de son code. Il y a une belle explication sur les alias C #, mentionnant également les avantages et les inconvénients, dans DotNetPearls ( http://www.dotnetperls.com/using-alias ).
using
comme outil d'alias. Cela m'embrouille en lisant le code - je sais déjà qu'il System.Collections
existe et a la IEnumerable<T>
classe. Utiliser un alias pour l'appeler quelque chose d'autre me l'obscurcit. Je vois using FooCollection = IEnumerable<Foo>
comme un moyen pour que les développeurs ultérieurs lisent le code et pensent: "Qu'est-ce que c'est que l'enfer FooCollection
et pourquoi n'y a-t-il pas une classe pour ça quelque part?" Je ne l'utilise jamais et découragerais son utilisation. Mais c'est peut-être juste moi.
Je l'ai beaucoup utilisé dans le passé pour travailler avec des flux d'entrée et de sortie. Vous pouvez les imbriquer correctement et cela supprime beaucoup des problèmes potentiels que vous rencontrez habituellement (en appelant automatiquement Dispose). Par exemple:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (System.IO.StreamReader sr = new StreamReader(bs))
{
string output = sr.ReadToEnd();
}
}
}
Le simple fait d'ajouter un petit quelque chose qui m'a surpris n'a pas été soulevé. La caractéristique la plus intéressante de l'utilisation (à mon avis) est que peu importe la façon dont vous quittez le bloc à l'aide, il disposera toujours de l'objet. Cela inclut les retours et les exceptions.
using (var db = new DbContext())
{
if(db.State == State.Closed) throw new Exception("Database connection is closed.");
return db.Something.ToList();
}
Peu importe que l'exception soit levée ou que la liste soit renvoyée. L'objet DbContext sera toujours supprimé.
Une autre grande utilité de l'utilisation consiste à instancier une boîte de dialogue modale.
Using frm as new Form1
Form1.ShowDialog
' do stuff here
End Using
En conclusion, lorsque vous utilisez une variable locale d'un type qui implémente IDisposable
, toujours , sans exception, utilisez using
1 .
Si vous utilisez des IDisposable
variables non locales , implémentez toujours le IDisposable
modèle .
Deux règles simples, sans exception 1 . Dans le cas contraire, la prévention des fuites de ressources est une véritable douleur dans les * ss.
1) : La seule exception est - lorsque vous gérez des exceptions. Il pourrait alors y avoir moins de code à appeler Dispose
explicitement dans le finally
bloc.
Vous pouvez utiliser l'espace de noms d'alias à l'aide de l'exemple suivant:
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
C'est ce qu'on appelle une directive utilisant l'alias , comme vous pouvez le voir, elle peut être utilisée pour masquer des références de longue haleine si vous souhaitez rendre évident dans votre code ce à quoi vous faites référence, par exemple
LegacyEntities.Account
au lieu de
CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account
ou simplement
Account // It is not obvious this is a legacy entity
Fait intéressant, vous pouvez également utiliser le modèle using / IDisposable pour d'autres choses intéressantes (comme l'autre point de la façon dont Rhino Mocks l'utilise). En gros, vous pouvez profiter du fait que le compilateur toujours .Dispose sur l'objet "utilisé". Si vous avez quelque chose qui doit se produire après une certaine opération ... quelque chose qui a un début et une fin définis ... alors vous pouvez simplement créer une classe IDisposable qui commence l'opération dans le constructeur, puis se termine dans la méthode Dispose.
Cela vous permet d'utiliser la syntaxe d'utilisation vraiment agréable pour indiquer le début et la fin explicites de ladite opération. C'est aussi ainsi que fonctionne le système.Transactions.
Lorsque vous utilisez ADO.NET, vous pouvez utiliser le travail au clavier pour des choses comme votre objet de connexion ou votre objet lecteur. De cette façon, une fois le bloc de code terminé, il supprimera automatiquement votre connexion.
"using" peut également être utilisé pour résoudre les conflits d'espace de nom. Voir http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ pour un court tutoriel que j'ai écrit sur le sujet.
public class ClassA:IDisposable
{
#region IDisposable Members
public void Dispose()
{
GC.SuppressFinalize(this);
}
#endregion
}
public void fn_Data()
{
using (ClassA ObjectName = new ClassA())
{
//use objectName
}
}
using est utilisé lorsque vous avez une ressource que vous souhaitez supprimer après son utilisation.
Par exemple, si vous allouez une ressource de fichier et que vous n'avez besoin de l'utiliser que dans une section de code pour un peu de lecture ou d'écriture, l'utilisation est utile pour éliminer la ressource de fichier dès que vous avez terminé.
La ressource utilisée doit implémenter IDisposable pour fonctionner correctement.
Exemple:
using (File file = new File (parameters))
{
*code to do stuff with the file*
}
Le mot clé using définit la portée de l'objet, puis supprime l'objet lorsque la portée est terminée. Par exemple.
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
Voir ici pour l'article MSDN sur le mot clé C # using.
Ce n'est pas très important, mais l'utilisation peut également être utilisée pour changer les ressources à la volée. Oui jetable comme mentionné précédemment, mais peut-être spécifiquement que vous ne voulez pas que les ressources ne correspondent pas aux autres ressources pendant le reste de votre exécution. Vous voulez donc vous en débarrasser pour qu'il n'interfère pas ailleurs.
Grâce aux commentaires ci-dessous, je vais nettoyer un peu ce post (je n'aurais pas dû utiliser les mots 'garbage collection' à l'époque, excuses):
lorsque vous utilisez using, il appellera la méthode Dispose () sur l'objet à la fin de la portée de l'utilisation. Vous pouvez donc avoir un peu de bon code de nettoyage dans votre méthode Dispose ().
Une puce ici qui, espérons-le, obtiendra peut-être ce non-marquage: si vous implémentez IDisposable, assurez-vous d'appeler GC.SuppressFinalize () dans votre implémentation Dispose (), sinon la collecte automatique des ordures essaiera de venir et de la finaliser à certains moments. point, ce qui au moins serait un gaspillage de ressources si vous en avez déjà Dispose () d.
Autre exemple d'utilisation raisonnable dans laquelle l'objet est immédiatement éliminé:
using (IDataReader myReader = DataFunctions.ExecuteReader(CommandType.Text, sql.ToString(), dp.Parameters, myConnectionString))
{
while (myReader.Read())
{
MyObject theObject = new MyObject();
theObject.PublicProperty = myReader.GetString(0);
myCollection.Add(theObject);
}
}
Tout ce qui se trouve à l'extérieur des accolades est éliminé, il est donc préférable de disposer vos objets si vous ne les utilisez pas. En effet, si vous avez un objet SqlDataAdapter et que vous ne l'utilisez qu'une seule fois dans le cycle de vie de l'application et que vous remplissez un seul ensemble de données et que vous n'en avez plus besoin, vous pouvez utiliser le code:
using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
// do stuff
} // here adapter_object is disposed automatically
L'instruction using fournit un mécanisme pratique pour utiliser correctement les objets IDisposable. En règle générale, lorsque vous utilisez un objet IDisposable, vous devez le déclarer et l'instancier dans une instruction using. L'instruction using appelle la méthode Dispose sur l'objet de la bonne manière et (lorsque vous l'utilisez comme indiqué précédemment), elle provoque également la sortie de l'objet lui-même dès que Dispose est appelé. Dans le bloc using, l'objet est en lecture seule et ne peut pas être modifié ou réaffecté.
Cela vient de: ici
Il peut également être utilisé pour créer des étendues pour l'exemple:
class LoggerScope:IDisposable {
static ThreadLocal<LoggerScope> threadScope =
new ThreadLocal<LoggerScope>();
private LoggerScope previous;
public static LoggerScope Current=> threadScope.Value;
public bool WithTime{get;}
public LoggerScope(bool withTime){
previous = threadScope.Value;
threadScope.Value = this;
WithTime=withTime;
}
public void Dispose(){
threadScope.Value = previous;
}
}
class Program {
public static void Main(params string[] args){
new Program().Run();
}
public void Run(){
log("something happend!");
using(new LoggerScope(false)){
log("the quick brown fox jumps over the lazy dog!");
using(new LoggerScope(true)){
log("nested scope!");
}
}
}
void log(string message){
if(LoggerScope.Current!=null){
Console.WriteLine(message);
if(LoggerScope.Current.WithTime){
Console.WriteLine(DateTime.Now);
}
}
}
}
L'instruction using indique à .NET de libérer l'objet spécifié dans le bloc using une fois qu'il n'est plus nécessaire. Vous devez donc utiliser le bloc «using» pour les classes qui nécessitent un nettoyage après elles, comme les types System.IO.
Il existe deux utilisations du using
mot clé en C # comme suit.
En tant que directive
En général, nous utilisons le using
mot - clé pour ajouter des espaces de noms dans les fichiers code-behind et de classe. Ensuite, il met à disposition toutes les classes, interfaces et classes abstraites ainsi que leurs méthodes et propriétés dans la page en cours.
Exemple:
using System.IO;
Comme une déclaration
C'est une autre façon d'utiliser le using
mot clé en C #. Il joue un rôle essentiel dans l'amélioration des performances de Garbage Collection.
le using
instruction garantit que Dispose () est appelée même si une exception se produit lorsque vous créez des objets et appelez des méthodes, des propriétés, etc. Dispose () est une méthode présente dans l'interface IDisposable qui aide à implémenter le garbage collection personnalisé. En d'autres termes, si je fais une opération de base de données (insérer, mettre à jour, supprimer) mais qu'en quelque sorte une exception se produit, alors l'instruction using ferme automatiquement la connexion. Pas besoin d'appeler explicitement la méthode de connexion Close ().
Un autre facteur important est qu'il contribue au regroupement de connexions. Le regroupement de connexions dans .NET permet d'éliminer la fermeture d'une connexion à une base de données plusieurs fois. Il envoie l'objet de connexion à un pool pour une utilisation future (prochain appel à la base de données). La prochaine fois qu'une connexion à la base de données est appelée à partir de votre application, le pool de connexions récupère les objets disponibles dans le pool. Cela permet donc d'améliorer les performances de l'application. Ainsi, lorsque nous utilisons l'instruction using, le contrôleur envoie automatiquement l'objet au pool de connexions, il n'est pas nécessaire d'appeler explicitement les méthodes Close () et Dispose ().
Vous pouvez faire la même chose que ce que fait l'instruction using en utilisant le bloc try-catch et appeler explicitement le Dispose () à l'intérieur du bloc finally. Mais l'instruction using effectue les appels automatiquement pour rendre le code plus propre et plus élégant. Dans le bloc using, l'objet est en lecture seule et ne peut pas être modifié ou réaffecté.
Exemple:
string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";
conn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));
}
}
Dans le code précédent, je ne ferme aucune connexion; il se fermera automatiquement. L' using
instruction appellera conn.Close () automatiquement en raison de l' using
instruction ( using (SqlConnection conn = new SqlConnection(connString)
) et la même chose pour un objet SqlDataReader. Et si une exception se produit, la connexion se ferme automatiquement.
Pour plus d'informations, consultez Utilisation et importance de l'utilisation en C # .
La syntaxe Rhino Mocks Record-playback fait un usage intéressant de using
.
l'utilisation comme instruction appelle automatiquement la disposition sur l'objet spécifié. L'objet doit implémenter l'interface IDisposable. Il est possible d'utiliser plusieurs objets dans une même instruction tant qu'ils sont du même type.
Le CLR convertit votre code en MSIL. Et l'instruction using est traduite en un essai et finalement un blocage. C'est ainsi que l'instruction using est représentée en IL. Une déclaration d'utilisation est traduite en trois parties: acquisition, utilisation et élimination. La ressource est d'abord acquise, puis l'utilisation est incluse dans une instruction try avec une clause finally. L'objet est ensuite supprimé dans la clause finally.
L'utilisation de Clause est utilisée pour définir la portée de la variable particulière. Par exemple:
Using(SqlConnection conn=new SqlConnection(ConnectionString)
{
Conn.Open()
// Execute sql statements here.
// You do not have to close the connection explicitly here as "USING" will close the connection once the object Conn becomes out of the defined scope.
}