Co nowego w języku C# 6What's New in C# 6

Wersja 6.0 C# zawiera wiele funkcji, które zwiększają produktywność dla deweloperów.The 6.0 release of C# contained many features that improve productivity for developers. Ogólny efekt tych funkcji jest pisania bardziej zwięzły widok kodu, który jest również bardziej czytelne.The overall effect of these features is that you write more concise code that is also more readable. Składnia zawiera mniej procedury dla wielu typowych rozwiązań.The syntax contains less ceremony for many common practices. Jest łatwiej zobaczyć założenia projektowe z mniej procedury.It's easier to see the design intent with less ceremony. Dowiedz się również, te funkcje i zostanie mu bardziej wydajnej pracy i napisać bardziej czytelny kod.Learn these features well, and you'll be more productive and write more readable code. Możesz skoncentrować się więcej na temat Twojej funkcji niż w konstrukcji języka.You can concentrate more on your features than on the constructs of the language.

W pozostałej części tego artykułu zawiera omówienie każdego z tych funkcji, za pomocą łącza, aby zapoznać się z każdej funkcji.The rest of this article provides an overview of each of these features, with a link to explore each feature. Możesz też zapoznać się z funkcjami w możliwość interaktywnego eksplorowania na C# 6 w sekcji samouczków.You can also explore the features in an interactive exploration on C# 6 in the tutorials section.

Auto właściwości tylko do odczytuRead-only auto-properties

Tylko do odczytu właściwości automatyczne zapewniają bardziej zwięzły widok składnię, aby utworzyć typy niezmienne.Read-only auto-properties provide a more concise syntax to create immutable types. Właściwość automatyczną deklarowana za pomocą tylko akcesor pobierania:You declare the auto-property with only a get accessor:

public string FirstName { get; }
public string LastName { get;  }

FirstName i LastName właściwości można ustawić tylko w treści konstruktora:The FirstName and LastName properties can be set only in the body of a constructor:

public Student(string firstName, string lastName)
{
    if (IsNullOrWhiteSpace(lastName))
        throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));
    FirstName = firstName;
    LastName = lastName;
}

Ustawiany LastName w innej metody generuje CS0200 błąd kompilacji:Trying to set LastName in another method generates a CS0200 compilation error:

public class Student
{
    public string LastName { get;  }

    public void ChangeName(string newLastName)
    {
        // Generates CS0200: Property or indexer cannot be assigned to -- it is read only
        LastName = newLastName;
    }
}

Ta funkcja umożliwia obsługę języka true Tworzenie typów niezmienne i używa składni właściwości automatycznej bardziej zwięzłe i wygodne.This feature enables true language support for creating immutable types and uses the more concise and convenient auto-property syntax.

Jeśli dodanie tej składni nie powoduje usunięcia dostępnej metody, to binarne zmiany zgodne.If adding this syntax doesn't remove an accessible method, it's a binary compatible change.

Inicjatory właściwości automatycznejAuto-property initializers

Właściwości automatyczne umożliwiają deklarowanie początkowa wartość auto właściwością jako część deklaracji właściwości.Auto-property initializers let you declare the initial value for an auto-property as part of the property declaration.

public ICollection<double> Grades { get; } = new List<double>();

Grades Elementu członkowskiego jest inicjowany, którym jest zdeklarowana.The Grades member is initialized where it's declared. Który sprawia, że łatwiej wykonać inicjowania dokładnie jeden raz.That makes it easier to perform the initialization exactly once. Inicjowanie jest częścią deklaracji właściwości, dzięki czemu łatwiej jest równoważne Alokacja magazynu za pomocą interfejsu publicznego dla Student obiektów.The initialization is part of the property declaration, making it easier to equate the storage allocation with the public interface for Student objects.

Elementy członkowskie z wyrażeniem w treści funkcjiExpression-bodied function members

Wiele elementów członkowskich, które należy zapisać są pojedynczej instrukcji, które mogą być pojedynczego wyrażenia.Many members that you write are single statements that could be single expressions. Zamiast niego zapisu elementu członkowskiego z wyrażeniem w treści.Write an expression-bodied member instead. Działa w przypadku metod i właściwości tylko do odczytu.It works for methods and read-only properties. Na przykład zastępowania metody ToString() często jest doskonałym kandydatem:For example, an override of ToString() is often a great candidate:

public override string ToString() => $"{LastName}, {FirstName}";

Dla właściwości tylko do odczytu, można również użyć następującej składni:You can also use this syntax for read-only properties:

public string FullName => $"{FirstName} {LastName}";

Zmienianie istniejącego elementu członkowskiego do elementu członkowskiego zabudowanego wyrażenie jest binarne zmiany zgodne.Changing an existing member to an expression bodied member is a binary compatible change.

Przy użyciu statycznejusing static

Przy użyciu statycznej ulepszenie umożliwia importowanie metod statycznych w tej samej klasy.The using static enhancement enables you to import the static methods of a single class. Należy określić klasę, którą używasz:You specify the class you're using:

using static System.Math;

Math Nie zawiera żadnych metod wystąpienia.The Math does not contain any instance methods. Można również użyć using static można zaimportować metody statyczne klasy dla klasy, która ma statycznych i metod wystąpienia.You can also use using static to import a class' static methods for a class that has both static and instance methods. Jednym z najbardziej przydatnych przykładów jest String:One of the most useful examples is String:

using static System.String;

Uwaga

Należy użyć w pełni kwalifikowaną nazwę klasy, System.String w statycznych przy użyciu instrukcji.You must use the fully qualified class name, System.String in a static using statement. Nie można użyć string słowa kluczowego zamiast tego.You cannot use the string keyword instead.

Po zaimportowaniu z static using instrukcji, metody rozszerzające są tylko w zakresie, gdy wywoływany przy użyciu składni wywołania metody rozszerzenia.When imported from a static using statement, extension methods are only in scope when called using the extension method invocation syntax. Nie są one w zakresie wywołanego jako metoda statyczna.They aren't in scope when called as a static method. Często zobaczysz następujący w kwerendach LINQ.You'll often see this in LINQ queries. Możesz zaimportować wzorzec LINQ, importując Enumerable, lub Queryable.You can import the LINQ pattern by importing Enumerable, or Queryable.

using static System.Linq.Enumerable;

Zwykle wywołują metody rozszerzenia za pomocą wyrażenia wywołania metody rozszerzenia.You typically call extension methods using extension method invocation expressions. Dodawanie nazwy klasy w rzadkich przypadkach, gdzie ich wywoływania przy użyciu wywołania metody statycznej składni usuwa niejednoznaczności.Adding the class name in the rare case where you call them using static method call syntax resolves ambiguity.

static using Dyrektywy również importuje wszystkie typy zagnieżdżone.The static using directive also imports any nested types. Wszelkie zagnieżdżone typy bez kwalifikacji można się odwoływać.You can reference any nested types without qualification.

Operatory warunkowe nullNull-conditional operators

Operatora warunkowego wartości null sprawia, że sprawdzenia wartości null znacznie łatwiejsze i płynny.The null conditional operator makes null checks much easier and fluid. Zastąp dostęp do elementu członkowskiego . z ?.:Replace the member access . with ?.:

var first = person?.FirstName; 

W poprzednim przykładzie, zmienna first przypisano null przypadku obiektu osoba null.In the preceding example, the variable first is assigned null if the person object is null. W przeciwnym razie jest przypisywana wartość FirstName właściwości.Otherwise, it is assigned the value of the FirstName property. Co najważniejsze ?. oznacza, że ten wiersz kodu nie generuje NullReferenceException Jeśli person zmienna jest null.Most importantly, the ?. means that this line of code doesn't generate a NullReferenceException if the person variable is null. Zamiast tego należy short-circuits i zwraca null.Instead, it short-circuits and returns null. Umożliwia także null operatora warunkowego dostępu do tablicy i indeksatora.You can also use a null conditional operator for array or indexer access. Zastąp [] z ?[] w wyrażeniu indeksu.Replace [] with ?[] in the index expression.

Poniższe wyrażenie zwraca string, niezależnie od tego, wartości person.The following expression returns a string, regardless of the value of person. Często używają tej konstrukcji z łączenie wartości null operatora, aby przypisać domyślnej wartości, gdy jedna z właściwości jest null.You often use this construct with the null coalescing operator to assign default values when one of the properties is null. Gdy wyrażenie short-circuits, null wartość zwracana jest wpisany pasuje pełnego wyrażenia.When the expression short-circuits, the null value returned is typed to match the full expression.

first = person?.FirstName ?? "Unspecified";

Można również użyć ?. do warunkowo wywołania metody.You can also use ?. to conditionally invoke methods. Najczęściej używane funkcje Członkowskie za pomocą operatora warunkowego wartości null jest bezpiecznie wywoływać delegatów (lub programy obsługi zdarzeń), może być null.The most common use of member functions with the null conditional operator is to safely invoke delegates (or event handlers) that may be null. Wywołasz pełnomocnika Invoke przy użyciu metody ?. operatora dostępu do elementu członkowskiego.You'll call the delegate's Invoke method using the ?. operator to access the member. Widać w przykładzie delegować wzorców artykułu.You can see an example in the delegate patterns article.

Reguły ?. operatora, upewnij się, że po lewej stronie operatora jest oceniane tylko raz.The rules of the ?. operator ensure that the left-hand side of the operator is evaluated only once. Umożliwia ona wiele idiomy, w tym w poniższym przykładzie przy użyciu programów obsługi zdarzeń:It enables many idioms, including the following example using event handlers:

// preferred in C# 6:
this.SomethingHappened?.Invoke(this, eventArgs);

Zapewnienie, że po lewej stronie jest oceniane tylko raz, umożliwi to również użyć dowolnego wyrażenia, w tym wywołania metody, z lewej strony ?.Ensuring that the left side is evaluated only once also enables you to use any expression, including method calls, on the left side of the ?.

Interpolacja ciągówString interpolation

Za pomocą C# 6, nowe Interpolacja ciągów funkcja umożliwia osadzanie wyrażeń w ciągu.With C# 6, the new string interpolation feature enables you to embed expressions in a string. Po prostu poprzedzony ciąg z $i używać wyrażeń między { i } zamiast liczby porządkowe:Simply preface the string with $and use expressions between { and } instead of ordinals:

public string FullName => $"{FirstName} {LastName}";

W tym przykładzie użyto właściwości podstawione wyrażeń.This example uses properties for the substituted expressions. Można użyć dowolnego wyrażenia.You can use any expression. Na przykład można obliczyć Średnia ocen studenta w ramach interpolacji:For example, you could compute a student's grade point average as part of the interpolation:

public string GetGradePointPercentage() =>
    $"Name: {LastName}, {FirstName}. G.P.A: {Grades.Average():F2}";

Poprzedni wiersz kodu formatuje wartość Grades.Average() jako liczba zmiennoprzecinkowa z dwóch miejsc po przecinku.The preceding line of code formats the value for Grades.Average() as a floating-point number with two decimal places.

Często należy sformatować ciąg powstały, używając określonej kultury.Often, you may need to format the string produced using a specific culture. Możesz użyć fakt, że obiekt utworzony przez Interpolacja ciągów, które mogą być niejawnie konwertowane na System.FormattableString.You use the fact that the object produced by a string interpolation can be implicitly converted to System.FormattableString. FormattableString Wystąpienie zawiera ciąg formatu złożonego oraz wynikiem oceny wyrażenia przed rozpoczęciem konwertowania ich na ciągi.The FormattableString instance contains the composite format string and the results of evaluating the expressions before converting them to strings. Użyj FormattableString.ToString(IFormatProvider) metodę, aby określić kulturę, gdy ciąg formatowania.Use the FormattableString.ToString(IFormatProvider) method to specify the culture when formatting a string. Poniższy przykład tworzy ciąg przy użyciu kultury niemiecki (de-DE).The following example produces a string using the German (de-DE) culture. (Domyślnie niemieckiego kultura używa znaku ',' jako separatora dziesiętnego i "." znaków jako separatora.)(By default, the German culture uses the ',' character for the decimal separator, and the '.' character as the thousands separator.)

FormattableString str = $"Average grade is {s.Grades.Average()}";
var gradeStr = str.ToString(new System.Globalization.CultureInfo("de-DE"));

Aby rozpocząć pracę z Interpolacja ciągów, zobacz interpolacji w ciągu C# interaktywnego samouczka Interpolacja ciągów artykułu, a Interpolacja w C# samouczka.To get started with string interpolation, see the String interpolation in C# interactive tutorial, the String interpolation article, and the String interpolation in C# tutorial.

Filtry wyjątkówException filters

Filtry wyjątków są klauzule określające stosowania klauzuli catch danego.Exception Filters are clauses that determine when a given catch clause should be applied. Jeśli w wyrażeniu użytym dla filtru wyjątku daje w wyniku true, klauzuli "catch" wykonuje jej normalne przetwarzanie po wystąpieniu wyjątku.If the expression used for an exception filter evaluates to true, the catch clause performs its normal processing on an exception. Jeśli wyrażenie ma false, a następnie catch klauzula jest pomijany.If the expression evaluates to false, then the catch clause is skipped. Jednym z zastosowań jest zbadanie informacje o wyjątku, aby określić, czy catch klauzuli może przetwarzać wyjątek:One use is to examine information about an exception to determine if a catch clause can process the exception:

public static async Task<string> MakeRequest()
{
    WebRequestHandler webRequestHandler = new WebRequestHandler();
    webRequestHandler.AllowAutoRedirect = false;
    using (HttpClient client = new HttpClient(webRequestHandler))
    {
        var stringTask = client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/about/");
        try
        {
            var responseText = await stringTask;
            return responseText;
        }
        catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
        {
            return "Site Moved";
        }
    }
}

nameof WyrażeniaThe nameof expression

nameof Wyrażenie ma nazwę symbolu.The nameof expression evaluates to the name of a symbol. Jest doskonałym sposobem na narzędzia do pracy w każdym przypadku, gdy potrzebna jest nazwa zmiennej, właściwość lub pole elementu członkowskiego.It's a great way to get tools working whenever you need the name of a variable, a property, or a member field. Jedną z najbardziej typowych używa nameof ma na celu dostarczenie nazwa symbolu, który spowodował wyjątek:One of the most common uses for nameof is to provide the name of a symbol that caused an exception:

if (IsNullOrWhiteSpace(lastName))
    throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));

Innym zastosowaniem jest z aplikacji opartych na XAML, które implementują INotifyPropertyChanged interfejsu:Another use is with XAML-based applications that implement the INotifyPropertyChanged interface:

public string LastName
{
    get { return lastName; }
    set
    {
        if (value != lastName)
        {
            lastName = value;
            PropertyChanged?.Invoke(this, 
                new PropertyChangedEventArgs(nameof(LastName)));
        }
    }
}
private string lastName;

Await w Catch i Finally blokujeAwait in Catch and Finally blocks

C# 5 ma również kilka ograniczeń wokół gdzie można umieścić await wyrażenia.C# 5 had several limitations around where you could place await expressions. Za pomocą C# 6, można teraz używać await w catch lub finally wyrażenia.With C# 6, you can now use await in catch or finally expressions. Jest to najczęściej używana w scenariuszach logowania:This is most often used with logging scenarios:

public static async Task<string> MakeRequestAndLogFailures()
{ 
    await logMethodEntrance();
    var client = new System.Net.Http.HttpClient();
    var streamTask = client.GetStringAsync("https://localHost:10000");
    try {
        var responseText = await streamTask;
        return responseText;
    } catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
    {
        await logError("Recovered from redirect", e);
        return "Site Moved";
    }
    finally
    {
        await logMethodExit();
        client.Dispose();
    }
}

Szczegóły implementacji, aby dodać await obsługi w catch i finally klauzule upewnij się, że zachowanie jest zgodne z zachowaniem dla kodu synchronicznego.The implementation details for adding await support inside catch and finally clauses ensure that the behavior is consistent with the behavior for synchronous code. Gdy kod jest wykonywany w catch lub finally klauzuli zgłasza wyjątek, wykonanie szuka odpowiedniej catch klauzuli w następnym bloku otaczającego.When code executed in a catch or finally clause throws, execution looks for a suitable catch clause in the next surrounding block. Jeśli było bieżący wyjątek, ten wyjątek zostanie utracony.If there was a current exception, that exception is lost. W tym celu za pomocą wyrażeń oczekiwane w catch i finally klauzule: odpowiedniej catch są wyszukiwane i bieżący wyjątek, jeśli istnieje, zostanie utracony.The same happens with awaited expressions in catch and finally clauses: a suitable catch is searched for, and the current exception, if any, is lost.

Uwaga

To zachowanie jest przyczyna, zaleca się zapisać catch i finally klauzule dokładnie, aby uniknąć wprowadzenia nowych wyjątków.This behavior is the reason it's recommended to write catch and finally clauses carefully, to avoid introducing new exceptions.

Inicjowanie asocjacyjnych kolekcji przy użyciu indeksatorówInitialize associative collections using indexers

Inicjatory indeksów to jedna z dwóch funkcji, które inicjatory kolekcji bardziej spójny z użyciem indeksu.Index Initializers is one of two features that make collection initializers more consistent with index usage. We wcześniejszych wersjach programu C#, można użyć inicjatory kolekcji z kolekcji stylów sekwencji, w tym Dictionary<TKey,TValue>, przez dodawanie nawiasów klamrowych otaczających klucz i wartość pary:In earlier releases of C#, you could use collection initializers with sequence style collections, including Dictionary<TKey,TValue>, by adding braces around key and value pairs:

private Dictionary<int, string> messages = new Dictionary<int, string>
{
    { 404, "Page not Found"},
    { 302, "Page moved, but left a forwarding address."},
    { 500, "The web server can't come out to play today."}
};

Możesz używać ich z Dictionary<TKey,TValue> kolekcje i inne typy miejsce dostępne Add metoda przyjmuje więcej niż jeden argument.You can use them with Dictionary<TKey,TValue> collections and other types where the accessible Add method accepts more than one argument. Nowa składnia obsługuje przypisanie do kolekcji przy użyciu indeksu:The new syntax supports assignment using an index into the collection:

private Dictionary<int, string> webErrors = new Dictionary<int, string>
{
    [404] = "Page not Found",
    [302] = "Page moved, but left a forwarding address.",
    [500] = "The web server can't come out to play today."
};

Tej funkcji oznacza, że kontenery asocjacyjne mogą być inicjowane przy użyciu składni podobnej do wprowadzonych w miejscu na potrzeby kontenerów sekwencji dla kilku wersji.This feature means that associative containers can be initialized using syntax similar to what's been in place for sequence containers for several versions.

Rozszerzenie Add metody inicjatory kolekcjiExtension Add methods in collection initializers

Kolejną funkcją, który ułatwia inicjowanie kolekcji jest możliwość używania — metoda rozszerzenia dla Add metody.Another feature that makes collection initialization easier is the ability to use an extension method for the Add method. Ta funkcja została dodana przez parzystość za pomocą Visual Basic.This feature was added for parity with Visual Basic. Ta funkcja jest najbardziej użyteczna, gdy masz klasę kolekcji niestandardowej, który ma metodę o innej nazwie do semantycznie dodawania nowych elementów.The feature is most useful when you have a custom collection class that has a method with a different name to semantically add new items.

Rozpoznanie przeciążenia ulepszoneImproved overload resolution

Funkcja ta ostatnia jest jeden, który prawdopodobnie nie będą zauważyć.This last feature is one you probably won't notice. Wystąpiły konstrukcje poprzedniej wersji kompilatora języka C# może mieć wykryto niektóre wywołania metody obejmujące wyrażenia lambda jest niejednoznaczny.There were constructs where the previous version of the C# compiler may have found some method calls involving lambda expressions ambiguous. Należy wziąć pod uwagę tę metodę:Consider this method:

static Task DoThings() 
{
     return Task.FromResult(0); 
}

We wcześniejszych wersjach języka C# wywołanie tej metody, przy użyciu składni metody grupy może zakończyć się niepowodzeniem:In earlier versions of C#, calling that method using the method group syntax would fail:

Task.Run(DoThings); 

Wcześniej kompilator nie można odróżnić prawidłowo między Task.Run(Action) i Task.Run(Func<Task>()).The earlier compiler couldn't distinguish correctly between Task.Run(Action) and Task.Run(Func<Task>()). W poprzednich wersjach należy użyć wyrażenia lambda jako argumentu:In previous versions, you'd need to use a lambda expression as an argument:

Task.Run(() => DoThings());

Kompilator języka C# 6 poprawnie ustali, że Task.Run(Func<Task>()) jest lepszym rozwiązaniem.The C# 6 compiler correctly determines that Task.Run(Func<Task>()) is a better choice.

Dane wyjściowe kompilatora deterministycznaDeterministic compiler output

-deterministic Opcji powoduje, że kompilator generuje zestaw identycznych danych wyjściowych dla bajt dla kolejnych kompilacje tych samych plików źródłowych.The -deterministic option instructs the compiler to produce a byte-for-byte identical output assembly for successive compilations of the same source files.

Domyślnie każdy kompilacji tworzy unikatowe dane wyjściowe w każdej kompilacji.By default, every compilation produces unique output on each compilation. Kompilator dodaje sygnaturę czasową i identyfikator GUID generowany na podstawie liczby losowe.The compiler adds a timestamp, and a GUID generated from random numbers. Użyj tej opcji, jeśli chcesz porównać dla bajt danych wyjściowych, aby upewnić się, że zostało skompilowane zachowania spójności w.You use this option if you want to compare the byte-for-byte output to ensure consistency across builds.

Aby uzyskać więcej informacji, zobacz — opcja kompilatora deterministyczne artykułu.For more information, see the -deterministic compiler option article.