Benutzer kokos beantwortete die wunderbare Frage nach den versteckten Funktionen von C # mit dem using
Schlüsselwort. Können Sie das näher erläutern? Wofür werden sie verwendet using
?
Benutzer kokos beantwortete die wunderbare Frage nach den versteckten Funktionen von C # mit dem using
Schlüsselwort. Können Sie das näher erläutern? Wofür werden sie verwendet using
?
Antworten:
Der Grund für die using
Anweisung besteht darin, sicherzustellen, dass das Objekt entsorgt wird, sobald es den Gültigkeitsbereich verlässt, und dass kein expliziter Code erforderlich ist, um sicherzustellen, dass dies geschieht.
Wie unter Grundlegendes zur Anweisung 'using' in C # (Codeprojekt) und Verwenden von Objekten, die IDisposable (Microsoft) implementieren, konvertiert der C # -Compiler
using (MyResource myRes = new MyResource())
{
myRes.DoSomething();
}
zu
{ // 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 führt eine neue Syntax mit dem Namen " using declarations " ein:
Eine using-Deklaration ist eine Variablendeklaration, der das using-Schlüsselwort vorangestellt ist. Es teilt dem Compiler mit, dass die deklarierte Variable am Ende des umschließenden Bereichs entsorgt werden soll.
Der äquivalente Code von oben wäre also:
using var myRes = new MyResource();
myRes.DoSomething();
Und wenn die Steuerung den enthaltenen Bereich verlässt (normalerweise eine Methode, kann aber auch ein Codeblock sein), myRes
wird sie entsorgt.
using
stellt sicher, dass dies Dispose
aufgerufen wird, sobald Sie mit dem Objekt fertig sind.
MyRessource
es sich um eine Struktur handelt. Es gibt offensichtlich keinen Test für die Nichtigkeit, aber auch kein Boxen zu IDisposable
. Ein eingeschränkter virtueller Anruf wird ausgegeben.
using
, ist die darin erstellte Variable schreibgeschützt. Ohne die using
Anweisung ist dies für lokale Variablen nicht möglich .
Da viele Leute immer noch tun:
using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
//code
}
Ich denke, viele Leute wissen immer noch nicht, dass Sie Folgendes tun können:
using (System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader("")) {
//code
}
Dinge wie dieses:
using (var conn = new SqlConnection("connection string"))
{
conn.Open();
// Execute SQL statement here on the connection you created
}
Dies SqlConnection
wird geschlossen, ohne dass die .Close()
Funktion explizit aufgerufen werden muss, und dies geschieht auch dann, wenn eine Ausnahme ausgelöst wird , ohne dass a erforderlich isttry
/ catch
/ finally
.
return
in der Mitte des using
Blocks befinden.
mit im Sinne von
using (var foo = new Bar())
{
Baz();
}
Ist eigentlich Abkürzung für einen try / finally-Block. Es entspricht dem Code:
var foo = new Bar();
try
{
Baz();
}
finally
{
foo.Dispose();
}
Sie werden natürlich feststellen, dass das erste Snippet viel prägnanter ist als das zweite und dass es viele Arten von Dingen gibt, die Sie möglicherweise als Bereinigung ausführen möchten, selbst wenn eine Ausnahme ausgelöst wird. Aus diesem Grund haben wir eine Klasse entwickelt, die wir Scope nennen und mit der Sie beliebigen Code in der Dispose-Methode ausführen können. Wenn Sie beispielsweise eine Eigenschaft namens IsWorking hatten, die Sie nach dem Versuch, eine Operation auszuführen, immer auf false setzen wollten, gehen Sie folgendermaßen vor:
using (new Scope(() => IsWorking = false))
{
IsWorking = true;
MundaneYetDangerousWork();
}
Lesen Sie hier mehr über unsere Lösung und wie wir sie abgeleitet haben .
In der Microsoft-Dokumentation heißt es, dass die Verwendung eine Doppelfunktion hat ( https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx ), sowohl als Direktive als auch in Anweisungen . Als Aussage , wie hier in anderen Antworten ausgeführt wurde, ist das Schlüsselwort im Wesentlichen syntaktischer Zucker, um einen Bereich zum Entsorgen eines IDisposable- Objekts zu bestimmen . Als Direktive wird sie routinemäßig zum Importieren von Namespaces und Typen verwendet. Auch als Direktive können Sie Aliase erstellen für Namespaces und Typen , wie im Buch "C # 5.0 auf den Punkt gebracht: Der endgültige Leitfaden" ( http://www.amazon.com/5-0-Nutshell-The-) beschrieben. Definitive-Reference-ebook / dp / B008E6I1K8), von Joseph und Ben Albahari. Ein Beispiel:
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;
}
}
}
Dies ist etwas, das mit Bedacht angewendet werden sollte, da der Missbrauch dieser Praxis die Klarheit des eigenen Codes beeinträchtigen kann. In DotNetPearls ( http://www.dotnetperls.com/using-alias ) gibt es eine nette Erklärung zu C # -Aliasen, in der auch Vor- und Nachteile erwähnt werden .
using
als Alias-Tool. Es verwirrt mich beim Lesen des Codes - ich weiß bereits, dass das System.Collections
existiert und die IEnumerable<T>
Klasse hat. Die Verwendung eines Alias, um es etwas anderes zu nennen, verschleiert es für mich. Ich sehe using FooCollection = IEnumerable<Foo>
eine Möglichkeit, spätere Entwickler dazu zu bringen, den Code zu lesen und zu denken: "Was zum Teufel ist ein FooCollection
und warum gibt es nicht irgendwo eine Klasse dafür?" Ich benutze es nie und würde von seiner Verwendung abraten. Aber das könnte nur ich sein.
Ich habe es in der Vergangenheit oft benutzt, um mit Eingabe- und Ausgabestreams zu arbeiten. Sie können sie gut verschachteln und es werden viele der potenziellen Probleme beseitigt, auf die Sie normalerweise stoßen (indem Sie automatisch dispose aufrufen). Zum Beispiel:
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();
}
}
}
Nur ein bisschen etwas hinzuzufügen, das mich überraschte, kam nicht auf. Das interessanteste Merkmal der Verwendung (meiner Meinung nach) ist, dass unabhängig davon, wie Sie den using-Block verlassen, das Objekt immer entsorgt wird. Dies schließt Rückgaben und Ausnahmen ein.
using (var db = new DbContext())
{
if(db.State == State.Closed) throw new Exception("Database connection is closed.");
return db.Something.ToList();
}
Es spielt keine Rolle, ob die Ausnahme ausgelöst oder die Liste zurückgegeben wird. Das DbContext-Objekt wird immer entsorgt.
Eine weitere großartige Verwendung ist das Instanziieren eines modalen Dialogs.
Using frm as new Form1
Form1.ShowDialog
' do stuff here
End Using
Abschließend , wenn Sie eine lokale Variable eines Typs verwenden , dass Geräte IDisposable
, immer , ohne Ausnahme, benutzen using
1 .
Wenn Sie nichtlokale IDisposable
Variablen verwenden, implementieren Sie immer das IDisposable
Muster .
Zwei einfache Regeln, keine Ausnahme 1 . Das Verhindern von Ressourcenlecks auf andere Weise ist ein echtes Problem.
1) : Die einzige Ausnahme ist - wenn Sie Ausnahmen behandeln. Es könnte dann weniger Code sein, um Dispose
explizit im finally
Block aufzurufen .
Sie können den Alias-Namespace anhand des folgenden Beispiels verwenden:
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
Wie Sie sehen, wird dies als Alias-Direktive verwendet. Sie kann verwendet werden, um langwierige Verweise auszublenden, wenn Sie in Ihrem Code deutlich machen möchten, worauf Sie sich beziehen, z
LegacyEntities.Account
anstatt
CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account
oder einfach
Account // It is not obvious this is a legacy entity
Interessanterweise können Sie das using / IDisposable-Muster auch für andere interessante Dinge verwenden (z. B. für den anderen Punkt, an dem Rhino Mocks es verwendet). Grundsätzlich können Sie die Tatsache nutzen, dass der Compiler immer wird .Dispose für das "verwendete" Objekt aufruft. Wenn Sie etwas haben, das nach einer bestimmten Operation geschehen muss ... etwas, das einen bestimmten Anfang und ein bestimmtes Ende hat ..., können Sie einfach eine IDisposable-Klasse erstellen, die die Operation im Konstruktor startet und dann in der Dispose-Methode beendet.
Auf diese Weise können Sie die wirklich nette Syntax verwenden, um den expliziten Start und das Ende dieser Operation zu kennzeichnen. So funktioniert auch das System.Transactions-Zeug.
Wenn Sie ADO.NET verwenden, können Sie das Keywork für Dinge wie Ihr Verbindungsobjekt oder Leserobjekt verwenden. Auf diese Weise wird Ihre Verbindung automatisch gelöscht, wenn der Codeblock abgeschlossen ist.
"using" kann auch verwendet werden, um Namensraumkonflikte zu lösen. Unter http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ finden Sie ein kurzes Tutorial, das ich zu diesem Thema geschrieben habe.
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 wird verwendet, wenn Sie über eine Ressource verfügen, die nach ihrer Verwendung entsorgt werden soll.
Wenn Sie beispielsweise eine Dateiressource zuweisen und sie nur in einem Codeabschnitt zum Lesen oder Schreiben verwenden müssen, ist die Verwendung hilfreich, um die Dateiressource zu entsorgen, sobald Sie fertig sind.
Die verwendete Ressource muss IDisposable implementieren, damit sie ordnungsgemäß funktioniert.
Beispiel:
using (File file = new File (parameters))
{
*code to do stuff with the file*
}
Das Schlüsselwort using definiert den Bereich für das Objekt und entsorgt das Objekt, wenn der Bereich vollständig ist. Zum Beispiel.
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
Sehen Sie hier für den MSDN - Artikel auf dem C # Schlüsselwort.
Nicht, dass es extrem wichtig wäre, aber die Verwendung kann auch verwendet werden, um Ressourcen im laufenden Betrieb zu ändern. Ja, wie bereits erwähnt verfügbar, aber möglicherweise möchten Sie nicht, dass die Ressourcen während des Restes Ihrer Ausführung nicht mit anderen Ressourcen übereinstimmen. Sie möchten es also entsorgen, damit es anderswo nicht stört.
Dank der folgenden Kommentare werde ich diesen Beitrag ein wenig bereinigen (ich hätte zu diesem Zeitpunkt nicht die Worte 'Garbage Collection' verwenden sollen, entschuldige
mich ): Wenn Sie using verwenden, wird die Dispose () -Methode für das Objekt aufgerufen am Ende des Anwendungsbereichs. Sie können also in Ihrer Dispose () -Methode eine Menge großartigen Bereinigungscodes haben.
Ein Aufzählungspunkt hier, der hoffentlich zu diesem nicht markierten Ergebnis führen wird: Wenn Sie IDisposable implementieren, stellen Sie sicher, dass Sie GC.SuppressFinalize () in Ihrer Dispose () -Implementierung aufrufen, da andernfalls die automatische Speicherbereinigung versucht, dies zu erreichen und bei einigen zu finalisieren Punkt, der zumindest eine Verschwendung von Ressourcen wäre, wenn Sie bereits () d davon entsorgen ().
Ein weiteres Beispiel für eine sinnvolle Verwendung, bei der das Objekt sofort entsorgt wird:
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);
}
}
Alles außerhalb der geschweiften Klammern ist entsorgt, daher ist es großartig, Ihre Objekte zu entsorgen, wenn Sie sie nicht verwenden. Dies liegt daran, dass Sie den folgenden Code verwenden können, wenn Sie ein SqlDataAdapter-Objekt haben und es nur einmal im Anwendungslebenszyklus verwenden und nur einen Datensatz füllen und ihn nicht mehr benötigen:
using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
// do stuff
} // here adapter_object is disposed automatically
Die using-Anweisung bietet einen praktischen Mechanismus zur korrekten Verwendung von IDisposable-Objekten. Wenn Sie ein IDisposable-Objekt verwenden, sollten Sie es in der Regel in einer using-Anweisung deklarieren und instanziieren. Die using-Anweisung ruft die Dispose-Methode für das Objekt auf die richtige Weise auf und bewirkt (wenn Sie sie wie oben gezeigt verwenden), dass das Objekt selbst den Gültigkeitsbereich verlässt, sobald Dispose aufgerufen wird. Innerhalb des using-Blocks ist das Objekt schreibgeschützt und kann nicht geändert oder neu zugewiesen werden.
Das kommt von: hier
Es kann auch zum Erstellen von Bereichen verwendet werden, zum Beispiel:
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);
}
}
}
}
Die using-Anweisung weist .NET an, das im using-Block angegebene Objekt freizugeben, sobald es nicht mehr benötigt wird. Daher sollten Sie den Block 'using' für Klassen verwenden, die nachträglich bereinigt werden müssen, z. B. System.IO-Typen.
Es gibt zwei Verwendungen des using
Schlüsselworts in C # wie folgt.
Als Richtlinie
Generell verwenden wir die using
Schlüsselwort, um Namespaces in CodeBehind- und Klassendateien hinzuzufügen. Anschließend werden alle Klassen, Schnittstellen und abstrakten Klassen sowie deren Methoden und Eigenschaften auf der aktuellen Seite verfügbar gemacht.
Beispiel:
using System.IO;
Als Aussage
Dies ist eine weitere Möglichkeit, das using
Schlüsselwort in C # zu verwenden. Es spielt eine wichtige Rolle bei der Verbesserung der Leistung in der Garbage Collection.
Die using
Anweisung stellt sicher, dass Dispose () aufgerufen wird, auch wenn beim Erstellen von Objekten und Aufrufen von Methoden, Eigenschaften usw. eine Ausnahme auftritt. Dispose () ist eine Methode, die in der IDisposable-Schnittstelle vorhanden ist und die Implementierung einer benutzerdefinierten Garbage Collection unterstützt. Mit anderen Worten, wenn ich eine Datenbankoperation ausführe (Einfügen, Aktualisieren, Löschen), aber irgendwie eine Ausnahme auftritt, schließt hier die using-Anweisung die Verbindung automatisch. Die Methode Close () muss nicht explizit aufgerufen werden.
Ein weiterer wichtiger Faktor ist, dass es beim Verbindungspooling hilft. Das Verbindungspooling in .NET hilft dabei, das mehrmalige Schließen einer Datenbankverbindung zu verhindern. Es sendet das Verbindungsobjekt zur zukünftigen Verwendung an einen Pool (nächster Datenbankaufruf). Wenn das nächste Mal eine Datenbankverbindung von Ihrer Anwendung aufgerufen wird, ruft der Verbindungspool die im Pool verfügbaren Objekte ab. Dies hilft, die Leistung der Anwendung zu verbessern. Wenn wir also die using-Anweisung verwenden, sendet der Controller das Objekt automatisch an den Verbindungspool. Es ist nicht erforderlich, die Methoden Close () und Dispose () explizit aufzurufen.
Sie können das Gleiche tun wie die using-Anweisung, indem Sie den try-catch-Block verwenden und Dispose () innerhalb des finally-Blocks explizit aufrufen. Die using-Anweisung führt die Aufrufe jedoch automatisch aus, um den Code sauberer und eleganter zu gestalten. Innerhalb des using-Blocks ist das Objekt schreibgeschützt und kann nicht geändert oder neu zugewiesen werden.
Beispiel:
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));
}
}
Im vorhergehenden Code schließe ich keine Verbindung; es wird automatisch geschlossen. Die using
Anweisung ruft conn.Close () aufgrund der using
Anweisung () automatisch auf using (SqlConnection conn = new SqlConnection(connString)
und dasselbe für ein SqlDataReader-Objekt. Und auch wenn eine Ausnahme auftritt, wird die Verbindung automatisch geschlossen.
Weitere Informationen finden Sie unter Verwendung und Bedeutung der Verwendung in C # .
Die Rhino Mocks Record-Playback-Syntax macht eine interessante Verwendung using
.
Die Verwendung als Anweisung ruft automatisch die Dispose für das angegebene Objekt auf. Das Objekt muss die IDisposable-Schnittstelle implementieren. Es ist möglich, mehrere Objekte in einer Anweisung zu verwenden, solange sie vom gleichen Typ sind.
Die CLR konvertiert Ihren Code in MSIL. Und die using-Anweisung wird in einen Versuch übersetzt und schließlich blockiert. So wird die using-Anweisung in IL dargestellt. Eine using-Anweisung besteht aus drei Teilen: Erwerb, Verwendung und Entsorgung. Die Ressource wird zuerst erfasst, dann wird die Verwendung in einer try-Anweisung mit einer finally-Klausel eingeschlossen. Das Objekt wird dann in der finally-Klausel entsorgt.
Mit Klausel wird der Bereich für die jeweilige Variable definiert. Zum Beispiel:
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.
}