Co nowego w języku C# 7.0What's new in C# 7.0

C# 7.0 dodaje wiele nowych funkcji do języka C#:C# 7.0 adds a number of new features to the C# language:

  • out Zmienneout variables
    • Można zadeklarować out wartości wbudowanych jako argumenty do metody, gdzie są używane.You can declare out values inline as arguments to the method where they're used.
  • KrotkiTuples
    • Można tworzyć lekkie, bez nazwy typów, które zawierają wiele pola publiczne.You can create lightweight, unnamed types that contain multiple public fields. Kompilatory i narzędzia IDE zrozumieć semantykę tych typów.Compilers and IDE tools understand the semantics of these types.
  • OdrzuceniaDiscards
    • Odrzuca są tymczasowego, tylko do zapisu zmienne używane w przypisania, jeśli nie dba o wartość przypisana.Discards are temporary, write-only variables used in assignments when you don't care about the value assigned. Są one najbardziej użyteczne, gdy dekonstrukcja krotek i typy zdefiniowane przez użytkownika, a także podczas wywoływania metody z out parametrów.They're most useful when deconstructing tuples and user-defined types, as well as when calling methods with out parameters.
  • Dopasowanie do wzorcaPattern Matching
    • Można utworzyć logikę rozgałęziania, na podstawie dowolnego typu i wartości elementów członkowskich tych typów.You can create branching logic based on arbitrary types and values of the members of those types.
  • ref Zmienne lokalne iref locals and returns
    • Metoda zmienne lokalne i wartości zwracane mogą być odwołania do innych magazynów.Method local variables and return values can be references to other storage.
  • Funkcje lokalneLocal Functions
    • Można zagnieżdżać funkcji w innych funkcjach, aby ograniczyć ich zakres i widoczność.You can nest functions inside other functions to limit their scope and visibility.
  • Więcej elementy członkowskie z wyrażeniemMore expression-bodied members
    • Zwiększył się listę elementów członkowskich, które można tworzyć za pomocą wyrażeń.The list of members that can be authored using expressions has grown.
  • throw Expressionsthrow Expressions
    • W konstrukcji kodu, które wcześniej nie były dozwolone, ponieważ może generować wyjątki throw został instrukcję.You can throw exceptions in code constructs that previously weren't allowed because throw was a statement.
  • Uogólnionego asynchroniczne typy zwracaneGeneralized async return types
    • Metody zadeklarowane za pomocą async modyfikator może zwrócić inne typy oprócz Task i Task<T>.Methods declared with the async modifier can return other types in addition to Task and Task<T>.
  • Ulepszenia składni literału liczbowegoNumeric literal syntax improvements
    • Nowe tokeny poprawić czytelność dla stałych numerycznych.New tokens improve readability for numeric constants.

W dalszej części tego artykułu zawiera omówienie każdej funkcji.The remainder of this article provides an overview of each feature. Dowiesz się jej uzasadnienie, dla każdej funkcji.For each feature, you'll learn the reasoning behind it. Dowiesz się, aby składnia.You'll learn the syntax. Możesz zapoznać się z tych funkcji w naszej możliwość interaktywnego eksplorowania z tych funkcji.You can explore these features in our interactive exploration of these features.

out Zmienneout variables

Istniejące składnia, która obsługuje out parametry została ulepszona w tej wersji.The existing syntax that supports out parameters has been improved in this version. Możesz teraz zadeklarować out zmiennych w liście argumentów wywołania metody, zamiast pisania instrukcji deklaracji oddzielnych:You can now declare out variables in the argument list of a method call, rather than writing a separate declaration statement:

if (int.TryParse(input, out int result))
    Console.WriteLine(result);
else
    Console.WriteLine("Could not parse input");

Możesz chcieć określić typ out zmiennych w celu uściślenia, jak pokazano powyżej.You may want to specify the type of the out variable for clarity, as shown above. Język obsługuje jednak przy użyciu niejawnie typizowanej zmiennej lokalnej:However, the language does support using an implicitly typed local variable:

if (int.TryParse(input, out var answer))
    Console.WriteLine(answer);
else
    Console.WriteLine("Could not parse input");
  • Kod jest łatwiejsza do odczytania.The code is easier to read.
    • Można zadeklarować zmiennej poza, której używasz, nie w kolejnym wierszu powyżej.You declare the out variable where you use it, not on another line above.
  • Nie ma potrzeby, aby przypisać wartość początkową.No need to assign an initial value.
    • DEKLARUJĄC out zmiennej, w przypadku, gdy jest używany w wywołaniu metody, nie można przypadkowo używać go przed przypisaniem go.By declaring the out variable where it's used in a method call, you can't accidentally use it before it is assigned.

KrotkiTuples

C# zapewnia rozbudowane składni klas i struktur, który służy do wyjaśnienia intencji Twojego projektu.C# provides a rich syntax for classes and structs that is used to explain your design intent. Jednak czasami takiej składni sformatowanego wymaga dodatkowej pracy dzięki korzyściom z minimalnym.But sometimes that rich syntax requires extra work with minimal benefit. Często mogą zapisywać metod wymagających prostą strukturę zawierających więcej niż jednego elementu danych.You may often write methods that need a simple structure containing more than one data element. Do obsługi tych scenariuszy krotek zostały dodane do języka C#.To support these scenarios tuples were added to C#. Kolekcje są strukturami danych uproszczone, zawierające wiele pól do reprezentowania składowych danych.Tuples are lightweight data structures that contain multiple fields to represent the data members. Pola nie są weryfikowane i nie można definiować własnych metod.The fields aren't validated, and you can't define your own methods

Uwaga

Spójne kolekcje były dostępne przed języka C# 7.0, ale zostały mało wydajne i miał Brak obsługi języka.Tuples were available before C# 7.0, but they were inefficient and had no language support. Oznacza to, że elementy krotki mogą być przywoływane tylko jako Item1, Item2 i tak dalej.This meant that tuple elements could only be referenced as Item1, Item2 and so on. C# 7.0 wprowadza obsługę krotek, co umożliwia semantycznego nazwy pól krotki przy użyciu typy krotki nowe, bardziej wydajne.C# 7.0 introduces language support for tuples, which enables semantic names for the fields of a tuple using new, more efficient tuple types.

Możesz utworzyć krotki przez przypisywanie wartości do każdego członka i opcjonalnie podania semantycznego nazwy do każdego z członków spójnej kolekcji:You can create a tuple by assigning a value to each member, and optionally providing semantic names to each of the members of the tuple:

(string Alpha, string Beta) namedLetters = ("a", "b");
Console.WriteLine($"{namedLetters.Alpha}, {namedLetters.Beta}");

namedLetters Krotka zawiera pola określone jako Alpha i Beta.The namedLetters tuple contains fields referred to as Alpha and Beta. Te nazwy istnieje tylko w czasie kompilacji i nie są zachowywane, na przykład podczas sprawdzania spójna kolekcja znajdująca się w czasie wykonywania przy użyciu odbicia.Those names exist only at compile time and aren't preserved, for example when inspecting the tuple using reflection at runtime.

W przypisaniu spójnej kolekcji można również określić nazwy pól po prawej stronie przypisania:In a tuple assignment, you can also specify the names of the fields on the right-hand side of the assignment:

var alphabetStart = (Alpha: "a", Beta: "b");
Console.WriteLine($"{alphabetStart.Alpha}, {alphabetStart.Beta}");

Mogą wystąpić sytuacje, gdy zachodzi potrzeba rozpakować elementy członkowskie spójnej kolekcji, które zostały zwrócone z metody.There may be times when you want to unpackage the members of a tuple that were returned from a method. Możecie od zadeklarowania zmiennych osobne dla każdej wartości w spójnej kolekcji.You can do that by declaring separate variables for each of the values in the tuple. Nazywa się to rozpakowywania dekonstrukcja spójnej kolekcji:This unpackaging is called deconstructing the tuple:

(int max, int min) = Range(numbers);
Console.WriteLine(max);
Console.WriteLine(min);

Możesz też podać podobne dekonstrukcja dla dowolnego typu na platformie .NET.You can also provide a similar deconstruction for any type in .NET. Piszesz Deconstruct metodę jako składową klasy.You write a Deconstruct method as a member of the class. Czy Deconstruct metoda zawiera zbiór out argumenty dla każdej właściwości, które mają zostać wyodrębnione.That Deconstruct method provides a set of out arguments for each of the properties you want to extract. Należy wziąć pod uwagę to Point klasę, która zapewnia metody deconstructor, która wyodrębnia X i Y współrzędnych:Consider this Point class that provides a deconstructor method that extracts the X and Y coordinates:

   public class Point
   {
       public Point(double x, double y) 
           => (X, Y) = (x, y);

       public double X { get; }
       public double Y { get; }

       public void Deconstruct(out double x, out double y) =>
           (x, y) = (X, Y);
   }

Można wyodrębnić poszczególne pola, przypisując Point do krotki:You can extract the individual fields by assigning a Point to a tuple:

var p = new Point(3.14, 2.71);
(double X, double Y) = p;

Możesz dowiedzieć się w bardziej szczegółowe informacje o krotek w artykułu krotek.You can learn more in depth about tuples in the tuples article.

OdrzuceniaDiscards

Często podczas dekonstrukcja krotki lub wywołanie metody z out parametrami, jest zmuszony do definiowania zmiennej z żądanymi wartościami nie interesuje i nie będą używane.Often when deconstructing a tuple or calling a method with out parameters, you're forced to define a variable whose value you don't care about and don't intend to use. C# dodaje obsługę odrzuca do obsługi tego scenariusza.C# adds support for discards to handle this scenario. Odrzucenia to zmienna tylko do zapisu, którego nazwa jest _ (znaki podkreślenia); można przypisać wszystkie wartości, które zamierzasz odrzucić do jednej zmiennej.A discard is a write-only variable whose name is _ (the underscore character); you can assign all of the values that you intend to discard to the single variable. Odrzucenia przypomina nieprzypisanej zmiennej; Oprócz instrukcji przypisania odrzuceń, nie można użyć w kodzie.A discard is like an unassigned variable; apart from the assignment statement, the discard can't be used in code.

Odrzuca są obsługiwane w następujących scenariuszach:Discards are supported in the following scenarios:

  • Gdy dekonstrukcja krotek lub typy zdefiniowane przez użytkownika.When deconstructing tuples or user-defined types.
  • Podczas wywoływania metody z się parametrów.When calling methods with out parameters.
  • We wzorcu, dopasowanie operację, podając jest i Przełącz instrukcji.In a pattern matching operation with the is and switch statements.
  • Jako identyfikator autonomicznej, aby jawnie Zidentyfikuj wartość do przypisania jako odrzucenia.As a standalone identifier when you want to explicitly identify the value of an assignment as a discard.

W poniższym przykładzie zdefiniowano QueryCityDataForYears metodę, która zwraca 6-spójną kolekcją, która zawiera dane jako uczestnik w mieście dla dwóch różnych lat.The following example defines a QueryCityDataForYears method that returns a 6-tuple that contains a data for a city for two different years. Wywołanie metody w przykładzie dotyczy tylko wartości dwóch populacji zwracany przez metodę i dlatego traktuje pozostałe wartości w spójnej kolekcji, ponieważ odrzuca, gdy jej deconstructs spójnej kolekcji.The method call in the example is concerned only with the two population values returned by the method and so treats the remaining values in the tuple as discards when it deconstructs the tuple.

using System;
using System.Collections.Generic;

public class Example
{
   public static void Main()
   {
       var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);

       Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}");
   }
   
   private static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2)
   {
      int population1 = 0, population2 = 0;
      double area = 0;
      
      if (name == "New York City") {
         area = 468.48; 
         if (year1 == 1960) {
            population1 = 7781984;
         }
         if (year2 == 2010) {
            population2 = 8175133;
         }
      return (name, area, year1, population1, year2, population2);
      }

      return ("", 0, 0, 0, 0, 0);
   }
}
// The example displays the following output:
//      Population change, 1960 to 2010: 393,149

Aby uzyskać więcej informacji, zobacz odrzuca.For more information, see Discards.

Dopasowanie do wzorcaPattern matching

Dopasowanie wzorca jest funkcją, która pozwala na implementowanie metody wysyłania we właściwościach innych niż typ obiektu.Pattern matching is a feature that allows you to implement method dispatch on properties other than the type of an object. Prawdopodobnie znasz metodę alokacji na podstawie typu obiektu.You're probably already familiar with method dispatch based on the type of an object. Programowanie zorientowane obiektowo, wirtualnych i zastąpienie metody zawiera składni języka, aby zaimplementować metodę wysyłania na podstawie typu obiektu.In object-oriented programming, virtual and override methods provide language syntax to implement method dispatching based on an object's type. Podstawowe i pochodne klasy dostarczać różne implementacje.Base and Derived classes provide different implementations. Wyrażenia dopasowania wzorca rozszerzyć tę koncepcję, dzięki czemu można łatwo zaimplementować podobnych wzorców wysyłania dla typów i elementów danych, które nie są powiązane przez hierarchię dziedziczenia.Pattern matching expressions extend this concept so that you can easily implement similar dispatch patterns for types and data elements that aren't related through an inheritance hierarchy.

Obsługa dopasowania do wzorca is wyrażeń i switch wyrażenia.Pattern matching supports is expressions and switch expressions. Każdy umożliwia zapoznanie się obiekt i jego właściwości w celu stwierdzenia, jeśli ten obiekt spełnia wzorzec używanych.Each enables inspecting an object and its properties to determine if that object satisfies the sought pattern. Możesz użyć when — słowo kluczowe, aby określić dodatkowe reguły do wzorca.You use the when keyword to specify additional rules to the pattern.

is Wyrażenia wzorca rozszerza znanej is operator można wysłać zapytania do obiektu o jej typ i przypisz wynik w jednej instrukcji.The is pattern expression extends the familiar is operator to query an object about its type and assign the result in one instruction. Poniższy kod umożliwia sprawdzenie, czy zmienna int, a jeśli tak, dodaje ją do sumy bieżącej:The following code checks if a variable is an int, and if so, adds it to the current sum:

if (input is int count)
    sum += count;

Ulepszenia pokazano w powyższym przykładzie małych is wyrażenia.The preceding small example demonstrates the enhancements to the is expression. Możesz przetestować względem typów wartości, a także typy odwołań i pomyślnego wyniku można przypisać do nowej zmiennej poprawnego typu.You can test against value types as well as reference types, and you can assign the successful result to a new variable of the correct type.

Wyrażenie dopasowania przełącznika ma dobrze znanej składni, w oparciu o switch instrukcja jest już częścią C# języka.The switch match expression has a familiar syntax, based on the switch statement already part of the C# language. Instrukcja switch zaktualizowane ma kilka nowych konstrukcji:The updated switch statement has several new constructs:

  • Typ zarządzania switch wyrażenia nie jest już ograniczony do typów całkowitych Enum typów string, lub typ dopuszczający wartość null, jednego z tych typów.The governing type of a switch expression is no longer restricted to integral types, Enum types, string, or a nullable type corresponding to one of those types. Dowolny typ mogą być używane.Any type may be used.
  • Możesz przetestować typ switch wyrażenie w każdym case etykiety.You can test the type of the switch expression in each case label. Podobnie jak w przypadku is wyrażenie nowej zmiennej może przypisać do tego typu.As with the is expression, you may assign a new variable to that type.
  • Możesz dodać when klauzuli w celu dalszego testowania warunków w tej zmiennej.You may add a when clause to further test conditions on that variable.
  • Kolejność case ważne jest teraz etykiety.The order of case labels is now important. Pierwszej gałęzi, aby dopasować jest wykonywana. inne są pomijane.The first branch to match is executed; others are skipped.

Poniższy kod demonstruje te nowe funkcje:The following code demonstrates these new features:

public static int SumPositiveNumbers(IEnumerable<object> sequence)
{
    int sum = 0;
    foreach (var i in sequence)
    {
        switch (i)
        {
            case 0:
                break;
            case IEnumerable<int> childSequence:
            {
                foreach(var item in childSequence)
                    sum += (item > 0) ? item : 0;
                break;
            }
            case int n when n > 0:
                sum += n;
                break;
            case null:
                throw new NullReferenceException("Null found in sequence");
            default:
                throw new InvalidOperationException("Unrecognized type");
        }
    }
    return sum;
}
  • case 0: jest dobrze znanych wzór stałej.case 0: is the familiar constant pattern.
  • case IEnumerable<int> childSequence: jest to wzorzec typu.case IEnumerable<int> childSequence: is a type pattern.
  • case int n when n > 0: jest to wzorzec typu przy użyciu dodatkowego when warunku.case int n when n > 0: is a type pattern with an additional when condition.
  • case null: jest wzorcem o wartości null.case null: is the null pattern.
  • default: jest to przypadek domyślny znanych.default: is the familiar default case.

Dowiedz się więcej na temat dopasowywania do wzorca w wzorzec dopasowywania w C# .You can learn more about pattern matching in Pattern Matching in C#.

Zmienne lokalne ref i zwracaRef locals and returns

Ta funkcja umożliwia algorytmy, które używają i zwracać odwołań do zmiennych określonych gdzie indziej.This feature enables algorithms that use and return references to variables defined elsewhere. Przykładem jest praca z macierzy dużych i znajdowanie w jednej lokalizacji, z określoną wspólną charakterystykę.One example is working with large matrices, and finding a single location with certain characteristics. Zwraca następującą metodę odwołania do tego magazynu w macierzy:The following method returns a reference to that storage in the matrix:

public static ref int Find(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return ref matrix[i, j];
    throw new InvalidOperationException("Not found");
}

Można zadeklarować wartość zwracana jako ref i zmodyfikować tę wartość w macierzy, jak pokazano w poniższym kodzie:You can declare the return value as a ref and modify that value in the matrix, as shown in the following code:

ref var item = ref MatrixSearch.Find(matrix, (val) => val == 42);
Console.WriteLine(item);
item = 24;
Console.WriteLine(matrix[4, 2]);

C# Język ma kilka reguł, które można chronić przed używaniem ref zmiennych lokalnych i zwraca:The C# language has several rules that protect you from misusing the ref locals and returns:

  • Należy dodać ref słowa kluczowego w podpisie metody i do wszystkich return instrukcji w metodzie.You must add the ref keyword to the method signature and to all return statements in a method.
    • Dzięki temu clear, metoda zwraca wartość przez odwołanie w całej metody.That makes it clear the method returns by reference throughout the method.
  • A ref return można przypisać do zmiennej wartości lub ref zmiennej.A ref return may be assigned to a value variable, or a ref variable.
    • Obiekt wywołujący kontroluje, czy wartość zwracana jest kopiowana, czy nie.The caller controls whether the return value is copied or not. Pominięcie ref modyfikator podczas przypisywania zwracana wartość wskazuje, że obiekt wywołujący chce kopię wartości, a nie odwołanie do magazynu.Omitting the ref modifier when assigning the return value indicates that the caller wants a copy of the value, not a reference to the storage.
  • Nie można przypisać wartość zwracaną standardową metodę, aby ref zmiennej lokalnej.You can't assign a standard method return value to a ref local variable.
    • Które nie zezwalają na instrukcjach, takich jak ref int i = sequence.Count();That disallows statements like ref int i = sequence.Count();
  • Nie można zwrócić ref do zmiennej, którego okres istnienia nie wykracza poza wykonywanie metody.You can't return a ref to a variable whose lifetime doesn't extend beyond the execution of the method.
    • Oznacza to, że nie można zwrócić odwołanie do zmiennej lokalnej lub zmienną o zakresie podobne.That means you can't return a reference to a local variable or a variable with a similar scope.
  • ref Zmienne lokalne i nie można używać metod asynchronicznych.ref locals and returns can't be used with async methods.
    • Kompilator nie wiadomo, jeśli przywoływany została ustawiona zmienna końcowej wartości po powrocie z metody asynchronicznej.The compiler can't know if the referenced variable has been set to its final value when the async method returns.

Dodatkowo zmienne lokalne ref i ref zwraca umożliwia algorytmy, które są bardziej wydajne, unikając kopiowania wartości lub wykonywanie operacji dereferencji wiele razy.The addition of ref locals and ref returns enables algorithms that are more efficient by avoiding copying values, or performing dereferencing operations multiple times.

Dodawanie ref wartość zwracana jest źródła zmiany zgodne.Adding ref to the return value is a source compatible change. Kompiluje istniejący kod, ale odwołania zwracana wartość jest kopiowany po przypisaniu.Existing code compiles, but the ref return value is copied when assigned. Obiekty wywołujące muszą zaktualizować magazyn dla zwracanej wartości ref zmienną lokalną, aby przechowywać zwracany jako odwołanie.Callers must update the storage for the return value to a ref local variable to store the return as a reference.

Aby uzyskać więcej informacji, zobacz ref — słowo kluczowe artykułu.For more information, see the ref keyword article.

Funkcje lokalneLocal functions

Wiele projektów dla klasy zawierają metody, które są wywoływane z tylko jedną lokalizację.Many designs for classes include methods that are called from only one location. Te dodatkowe metody prywatnej Zachowaj każdej metody niewielkiego i skupionego projektu.These additional private methods keep each method small and focused. Funkcje lokalne umożliwiają deklarowanie metody w kontekście innej metody.Local functions enable you to declare methods inside the context of another method. Funkcje lokalne ułatwiają czytelnicy klasy wyświetlić tylko wywołać lokalnego metody z kontekstu, w którym jest zdeklarowana.Local functions make it easier for readers of the class to see that the local method is only called from the context in which it is declared.

Istnieją dwie typowe przypadki użycia dla funkcji lokalnych: metody iteratora publicznych i metod asynchronicznych publicznych.There are two common use cases for local functions: public iterator methods and public async methods. Oba rodzaje metod wygenerować kod, który zgłasza błędy nowsze niż programiści mogą oczekiwać.Both types of methods generate code that reports errors later than programmers might expect. W metodzie iteratora wszelkie wyjątki pojawiają się tylko podczas wywoływania kodu, który wylicza zwracanej sekwencji.In iterator methods, any exceptions are observed only when calling code that enumerates the returned sequence. W metodach asynchronicznych wyjątków tylko obserwuje się kiedy zwracanego Task jest oczekiwane.In async methods, any exceptions are only observed when the returned Task is awaited. W poniższym przykładzie pokazano oddzielający Walidacja parametru od implementacji iteratora, przy użyciu funkcji lokalnego:The following example demonstrates separating parameter validation from the iterator implementation using a local function:

public static IEnumerable<char> AlphabetSubset3(char start, char end)
{
    if (start < 'a' || start > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if (end < 'a' || end > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");

    return alphabetSubsetImplementation();

    IEnumerable<char> alphabetSubsetImplementation()
    {
        for (var c = start; c < end; c++)
            yield return c;
    }
}

Można zastosować za pomocą tej samej techniki async metod w celu zapewnienia, że wynikające z walidacji argumentów zgłaszania wyjątków przed rozpoczęciem pracy asynchronicznej:The same technique can be employed with async methods to ensure that exceptions arising from argument validation are thrown before the asynchronous work begins:

public Task<string> PerformLongRunningWork(string address, int index, string name)
{
    if (string.IsNullOrWhiteSpace(address))
        throw new ArgumentException(message: "An address is required", paramName: nameof(address));
    if (index < 0)
        throw new ArgumentOutOfRangeException(paramName: nameof(index), message: "The index must be non-negative");
    if (string.IsNullOrWhiteSpace(name))
        throw new ArgumentException(message: "You must supply a name", paramName: nameof(name));

    return longRunningWorkImplementation();

    async Task<string> longRunningWorkImplementation()
    {
        var interimResult = await FirstWork(address);
        var secondResult = await SecondStep(index, name);
        return $"The results are {interimResult} and {secondResult}. Enjoy.";
    }
}

Uwaga

Niektóre projekty, które są obsługiwane przez funkcje lokalne mogą być również wykonywane przy użyciu wyrażeń lambda.Some of the designs that are supported by local functions could also be accomplished using lambda expressions. Te zainteresowane można Dowiedz się więcej o różnicachThose interested can read more about the differences

Więcej elementy członkowskie z wyrażeniemMore expression-bodied members

C# 6 wprowadzono elementy członkowskie z wyrażeniem dla elementów członkowskich i właściwości tylko do odczytu.C# 6 introduced expression-bodied members for member functions, and read-only properties. C# 7.0 rozwija dozwolonych elementów członkowskich, które można zaimplementować jako wyrażenia.C# 7.0 expands the allowed members that can be implemented as expressions. W języku C# 7.0, można zaimplementować konstruktory, finalizatory, i get i set metod dostępu na właściwości i indeksatorów .In C# 7.0, you can implement constructors, finalizers, and get and set accessors on properties and indexers. Poniższy kod przedstawia przykłady każdego z nich:The following code shows examples of each:

// Expression-bodied constructor
public ExpressionMembersExample(string label) => this.Label = label;

// Expression-bodied finalizer
~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");

private string label;

// Expression-bodied get / set accessors.
public string Label
{
    get => label;
    set => this.label = value ?? "Default label";
}

Uwaga

W tym przykładzie nie potrzebuje finalizatora, jednak wyświetleniem pokazano składnię.This example does not need a finalizer, but it is shown to demonstrate the syntax. Nie należy implementować finalizator w klasie, chyba że jest to niezbędne zwolnić niezarządzane zasoby.You should not implement a finalizer in your class unless it is necessary to release unmanaged resources. Należy również rozważyć użycie SafeHandle klasy zamiast na zarządzaniu bezpośrednio niezarządzane zasoby.You should also consider using the SafeHandle class instead of managing unmanaged resources directly.

Te nowe lokalizacje dla elementy członkowskie z wyrażeniem reprezentują ważnym kamieniem milowym dla C# języka: Te funkcje zostały zaimplementowane przez członków społeczności nad typu open-source Roslyn projektu.These new locations for expression-bodied members represent an important milestone for the C# language: These features were implemented by community members working on the open-source Roslyn project.

Zmiana metody do elementu członkowskiego zabudowanego wyrażenie jest binarne zmiany zgodne.Changing a method to an expression bodied member is a binary compatible change.

Wyrażenia throwThrow expressions

W języku C# throw zawsze było instrukcję.In C#, throw has always been a statement. Ponieważ throw jest instrukcją nie wyrażenie wystąpiły C# konstrukcje, których nie używasz go.Because throw is a statement, not an expression, there were C# constructs where you couldn't use it. Uwzględnione są niektóre wyrażenia lambda, wyrażenia warunkowe i wyrażenia łączące wartości null.These included conditional expressions, null coalescing expressions, and some lambda expressions. Dodanie elementy członkowskie z wyrażeniem dodanie większej liczby lokalizacji gdzie throw wyrażeń może okazać się przydatne.The addition of expression-bodied members adds more locations where throw expressions would be useful. Dzięki czemu można tworzyć dowolne te konstrukcje C# wprowadza 7.0 wyrażeń throw.So that you can write any of these constructs, C# 7.0 introduces throw expressions.

To dodawanie ułatwia pisanie kodu oparte na wyrażeniach więcej.This addition makes it easier to write more expression-based code. Nie potrzebujesz dodatkowych instrukcji sprawdzania błędów.You don't need additional statements for error checking.

Uogólnionego asynchroniczne typy zwracaneGeneralized async return types

Zwracanie Task obiekt z metody asynchronicznej może prowadzić do wąskich gardeł wydajności w niektórych ścieżek.Returning a Task object from async methods can introduce performance bottlenecks in certain paths. Task jest typem referencyjnym, więc za jego pomocą oznacza przydzielanie obiektu.Task is a reference type, so using it means allocating an object. W przypadkach, w którym metoda jest zadeklarowana za pomocą async modyfikator zwraca wynik pamięci podręcznej lub zakończeniu synchronicznie, dodatkowe alokacji może stać się koszt znaczną ilość czasu, w sekcji krytycznych wydajność kodu.In cases where a method declared with the async modifier returns a cached result, or completes synchronously, the extra allocations can become a significant time cost in performance critical sections of code. Może być kosztowne, jeśli te przydziały występują w ścisłej pętli.It can become costly if those allocations occur in tight loops.

Nowa funkcja języka oznacza, że metoda asynchroniczna, zwracane typy nie są ograniczone do Task, Task<T>, i void.The new language feature means that async method return types aren't limited to Task, Task<T>, and void. Zwrócony typ nadal musi spełniać wzorca asynchronicznego, co oznacza GetAwaiter metody muszą być dostępne.The returned type must still satisfy the async pattern, meaning a GetAwaiter method must be accessible. Przykład jednego konkretnego ValueTask typ został dodany do programu .NET framework, aby skorzystać z tej nowej funkcji języka:As one concrete example, the ValueTask type has been added to the .NET framework to make use of this new language feature:

public async ValueTask<int> Func()
{
    await Task.Delay(100);
    return 5;
}

Uwaga

Dodaj pakiet NuGet System.Threading.Tasks.Extensions aby można było używać ValueTask<TResult> typu.You need to add the NuGet package System.Threading.Tasks.Extensions in order to use the ValueTask<TResult> type.

To rozszerzenie jest najbardziej użyteczne dla autorów biblioteki uniknąć przyznawania Task w wydajności kodu krytycznego.This enhancement is most useful for library authors to avoid allocating a Task in performance critical code.

Ulepszenia składni literału liczbowegoNumeric literal syntax improvements

Misreading stałych numerycznych może utrudnić rozumienie kodu, odczytując je po raz pierwszy.Misreading numeric constants can make it harder to understand code when reading it for the first time. Masek bitowych lub innych symboliczne wartości są podatne na nieporozumienia.Bit masks or other symbolic values are prone to misunderstanding. C#7.0 zawiera dwie nowe funkcje, aby zapisać numery w najbardziej czytelny sposób związane z zamierzonym użyciem: literały binarne, i separatory cyfr.C# 7.0 includes two new features to write numbers in the most readable fashion for the intended use: binary literals, and digit separators.

Czasów przy tworzeniu masek bitowych lub zawsze wtedy, gdy binarna reprezentacja liczby sprawia, że najbardziej czytelne kodu, zapisać tę liczbę w pliku binarnego:For those times when you're creating bit masks, or whenever a binary representation of a number makes the most readable code, write that number in binary:

public const int Sixteen =   0b0001_0000;
public const int ThirtyTwo = 0b0010_0000;
public const int SixtyFour = 0b0100_0000;
public const int OneHundredTwentyEight = 0b1000_0000;

0b Na początku stała wskazuje, że liczba jest zapisywany jako wartości binarnej.The 0b at the beginning of the constant indicates that the number is written as a binary number. Binarne wartości można uzyskać długości, więc jest często łatwiej zobaczyć wzorców bitowych, wprowadzając _ jako separator cyfr, jak pokazano powyżej w stałej binarnego.Binary numbers can get long, so it's often easier to see the bit patterns by introducing the _ as a digit separator, as shown above in the binary constant. Separator cyfr może występować w dowolnym miejscu w stałej.The digit separator can appear anywhere in the constant. W przypadku podstawowej liczb 10, jest często używa się tysięcy separatora:For base 10 numbers, it is common to use it as a thousands separator:

public const long BillionsAndBillions = 100_000_000_000;

Separator cyfr, może być używany z decimal, float, i double również typy:The digit separator can be used with decimal, float, and double types as well:

public const double AvogadroConstant = 6.022_140_857_747_474e23;
public const decimal GoldenRatio = 1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179M;

Razem wzięte, można zadeklarować stałych numerycznych za pomocą znacznie więcej czytelności.Taken together, you can declare numeric constants with much more readability.