"Musterbasiertes verwenden" und "Verwenden von Deklarationen""pattern-based using" and "using declarations"

ZusammenfassungSummary

Die Sprache fügt zwei neue Funktionen um die using-Anweisung hinzu, um die Ressourcenverwaltung zu vereinfachen: using sollten zusätzlich zu IDisposable ein verwerfbares Muster erkennen und der Sprache eine using Deklaration hinzufügen.The language will add two new capabilities around the using statement in order to make resource management simpler: using should recognize a disposable pattern in addition to IDisposable and add a using declaration to the language.

MotivationMotivation

Die using-Anweisung ist zurzeit ein effektives Tool für die Ressourcenverwaltung, erfordert aber eine ganze Stunde.The using statement is an effective tool for resource management today but it requires quite a bit of ceremony. Methoden mit einer Reihe von Ressourcen, die verwaltet werden müssen, können mit einer Reihe von using-Anweisungen syntaktisch blockiert werden.Methods that have a number of resources to manage can get syntactically bogged down with a series of using statements. Diese Syntax Belastung ist ausreichend, dass die meisten Richtlinien zum Codierungsstil in diesem Szenario explizit mit geschweiften Klammern zu tun haben.This syntax burden is enough that most coding style guidelines explicitly have an exception around braces for this scenario.

Mit der using Deklaration wird C# ein Großteil der Zeremonie an dieser Stelle entfernt und mit anderen Sprachen, die Ressourcen Verwaltungs Blöcke einschließen, abgerufen.The using declaration removes much of the ceremony here and gets C# on par with other languages that include resource management blocks. Außerdem ermöglicht die Musterbasierte using Entwicklern, den Satz von Typen zu erweitern, die an dieser Stelle teilnehmen können.Additionally the pattern-based using lets developers expand the set of types that can participate here. In vielen Fällen ist es nicht mehr erforderlich, Wrapper Typen zu erstellen, die nur vorhanden sind, um Werte in einer using Anweisung zu verwenden.In many cases removing the need to create wrapper types that only exist to allow for a values use in a using statement.

Diese Features ermöglichen es Entwicklern, die Szenarien, in denen using angewendet werden können, zu vereinfachen und zu erweitern.Together these features allow developers to simplify and expand the scenarios where using can be applied.

Detaillierter EntwurfDetailed Design

using-Deklarationusing declaration

Die Sprache ermöglicht das Hinzufügen von using zu einer lokalen Variablen Deklaration.The language will allow for using to be added to a local variable declaration. Eine solche Deklaration hat denselben Effekt wie das Deklarieren der Variablen in einer using-Anweisung am gleichen Speicherort.Such a declaration will have the same effect as declaring the variable in a using statement at the same location.

if (...) 
{ 
   using FileStream f = new FileStream(@"C:\users\jaredpar\using.md");
   // statements
}

// Equivalent to 
if (...) 
{ 
   using (FileStream f = new FileStream(@"C:\users\jaredpar\using.md")) 
   {
    // statements
   }
}

Die Lebensdauer eines using lokalen wird bis zum Ende des Bereichs erweitert, in dem er deklariert ist.The lifetime of a using local will extend to the end of the scope in which it is declared. Die using lokalen Variablen werden dann in umgekehrter Reihenfolge verworfen, in der Sie deklariert werden.The using locals will then be disposed in the reverse order in which they are declared.

{ 
    using var f1 = new FileStream("...");
    using var f2 = new FileStream("..."), f3 = new FileStream("...");
    ...
    // Dispose f3
    // Dispose f2 
    // Dispose f1
}

Es gibt keine Einschränkungen in Bezug auf gotooder ein anderes Ablauf Steuerungs Konstrukt im Zusammenhang mit einer using Deklaration.There are no restrictions around goto, or any other control flow construct in the face of a using declaration. Stattdessen verhält sich der Code genauso wie für die entsprechende using-Anweisung:Instead the code acts just as it would for the equivalent using statement:

{
    using var f1 = new FileStream("...");
  target:
    using var f2 = new FileStream("...");
    if (someCondition) 
    {
        // Causes f2 to be disposed but has no effect on f1
        goto target;
    }
}

Eine lokale Deklaration, die in einer using lokalen Deklaration deklariert wird, ist implizit schreibgeschützt.A local declared in a using local declaration will be implicitly read-only. Dies entspricht dem Verhalten der in einer using Anweisung deklarierten lokalen Variablen.This matches the behavior of locals declared in a using statement.

Die Sprachgrammatik für using Deklarationen lautet wie folgt:The language grammar for using declarations will be the following:

local-using-declaration:
  using type using-declarators

using-declarators:
  using-declarator
  using-declarators , using-declarator
  
using-declarator:
  identifier = expression

Einschränkungen bei der using Deklaration:Restrictions around using declaration:

  • Darf nicht direkt in einer case Bezeichnung vorkommen, sondern muss sich innerhalb eines Blocks innerhalb der case Bezeichnung befinden.May not appear directly inside a case label but instead must be within a block inside the case label.
  • Kann nicht als Teil einer out Variablen Deklaration angezeigt werden.May not appear as part of an out variable declaration.
  • Für jeden Deklarator muss ein Initialisierer vorhanden sein.Must have an initializer for each declarator.
  • Der lokale Typ muss implizit konvertierbar sein, um das using Muster zu IDisposable oder zu erfüllen.The local type must be implicitly convertible to IDisposable or fulfill the using pattern.

Muster basiert mithilfe vonpattern-based using

Die Sprache fügt das Konzept eines verwerfbaren Musters hinzu: ein Typ, der über eine Dispose Instanzmethode verfügt, auf die zugegriffen werden kann.The language will add the notion of a disposable pattern: that is a type which has an accessible Dispose instance method. Typen, die das verwerfbare Muster erfüllen, können an einer using Anweisung oder Deklaration teilnehmen, ohne dass IDisposableimplementiert werden muss.Types which fit the disposable pattern can participate in a using statement or declaration without being required to implement IDisposable.

class Resource
{ 
    public void Dispose() { ... }
}

using (var r = new Resource())
{
    // statements
}

Auf diese Weise können Entwickler using in einer Reihe neuer Szenarien nutzen:This will allow developers to leverage using in a number of new scenarios:

  • ref struct: diese Typen können heute keine Schnittstellen implementieren und können daher nicht an using Anweisungen teilnehmen.ref struct: These types can't implement interfaces today and hence can't participate in using statements.
  • Erweiterungs Methoden ermöglichen Entwicklern das Erweitern von Typen in anderen Assemblys, sodass Sie an using-Anweisungen teilnehmen können.Extension methods will allow developers to augment types in other assemblies to participate in using statements.

In der Situation, in der ein Typ implizit in IDisposable konvertiert werden kann, und auch das verwerfbare Muster entspricht, wird IDisposable bevorzugt.In the situation where a type can be implicitly converted to IDisposable and also fits the disposable pattern, then IDisposable will be preferred. Wenngleich dies der gegen übergesetzte Ansatz von foreach ist (Muster, das gegenüber Interface bevorzugt ist), ist es für Abwärtskompatibilität erforderlich.While this takes the opposite approach of foreach (pattern preferred over interface) it is necessary for backwards compatibility.

Dies gilt auch für die gleichen Einschränkungen wie für eine herkömmliche using-Anweisung: lokale Variablen, die im using deklariert sind, sind schreibgeschützt, ein null Wert führt nicht dazu, dass eine Ausnahme ausgelöst wird usw... Die Codegenerierung unterscheidet sich nur darin, dass vor dem Aufrufen von "verwerfen" keine Umwandlung in IDisposable erfolgt:The same restrictions from a traditional using statement apply here as well: local variables declared in the using are read-only, a null value will not cause an exception to be thrown, etc ... The code generation will be different only in that there will not be a cast to IDisposable before calling Dispose:

{
      Resource r = new Resource();
      try {
            // statements
      }
      finally {
            if (resource != null) resource.Dispose();
      }
}

Um dem verwerfbaren Muster gerecht zu werden, muss auf die Dispose Methode zugegriffen werden können, Parameter lose Parameter und haben einen void Rückgabetyp.In order to fit the disposable pattern the Dispose method must be accessible, parameterless and have a void return type. Es gibt keine weiteren Einschränkungen.There are no other restrictions. Dies bedeutet explizit, dass hier Erweiterungs Methoden verwendet werden können.This explicitly means that extension methods can be used here.

ÜberlegungenConsiderations

Case-Bezeichnungen ohne Blöckecase labels without blocks

Eine using declaration ist aufgrund von Komplikationen bei der tatsächlichen Lebensdauer direkt innerhalb einer case Bezeichnung unzulässig.A using declaration is illegal directly inside a case label due to complications around its actual lifetime. Eine mögliche Lösung besteht darin, die gleiche Lebensdauer wie eine out var am gleichen Speicherort anzugeben.One potential solution is to simply give it the same lifetime as an out var in the same location. Dies war die zusätzliche Komplexität der Featureimplementierung und die einfache Problem Umgehung (fügen Sie der case Bezeichnung einen Block hinzu) nicht rechtfertigen diese Route.It was deemed the extra complexity to the feature implementation and the ease of the work around (just add a block to the case label) didn't justify taking this route.

Zukünftige ErweiterungenFuture Expansions

lokale Variablenfixed locals

Eine fixed-Anweisung verfügt über alle Eigenschaften von using-Anweisungen, die die Möglichkeit haben, using lokale zu haben.A fixed statement has all of the properties of using statements that motivated the ability to have using locals. Beachten Sie, dass Sie dieses Feature auch auf fixed lokalen Erweiterungen erweitern müssen.Consideration should be given to extending this feature to fixed locals as well. Die Lebensdauer-und Bestell Regeln sollten für using und fixed hier gleichermaßen gut anwendbar sein.The lifetime and ordering rules should apply equally well for using and fixed here.