Read-only auto-properties provide a more concise syntax to create immutable types. You declare the auto-property with only a get accessor. These can be set only in the body of a constructor
public string FirstName { get; }
public string LastName { get; }
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>();
Many members that you write are single statements that could be single expressions. Write an expression-bodied member instead. It works for methods and read-only properties.
methods:
public override string ToString() => $"{LastName}, {FirstName}";
properties:
public string FullName => $"{FirstName} {LastName}";
The using static enhancement enables you to import the static methods of a single class. You specify the class you're using.
using static System.String;
using static System.Math;
You must use the fully qualified class name, System.String
in a static using statement. You cannot use the string
keyword instead.
When imported from a static using
statement, extension methods are only in scope when called using the extension method invocation syntax. They aren't in scope when called as a static method.
The null conditional operator makes null checks much easier and fluid.
var first = person?.FirstName;
first = person?.FirstName ?? "Unspecified";
this.SomethingHappened?.Invoke(this, eventArgs);
feature enables you to embed expressions in a string. Simply preface the string with $
and use expressions between {
and }
instead of ordinals.
public string FullName => $"{FirstName} {LastName}";
FormattableString str = $"Average grade is {s.Grades.Average()}";
var gradeStr = str.ToString(new System.Globalization.CultureInfo("de-DE"));
Exception Filters are clauses that determine when a given catch clause should be applied. If the expression used for an exception filter evaluates to true
, the catch clause performs its normal processing on an exception. If the expression evaluates to false
, then the catch
clause is skipped.
catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
{
return "Site Moved";
}
The nameof expression evaluates to the name of a symbol. It's a great way to get tools working whenever you need the name of a variable, a property, or a member field. One of the most common uses for nameof is to provide the name of a symbol that caused an exception
C# 5 had several limitations around where you could place await
expressions. With C# 6, you can use await
in catch
or finally
expression
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)
{
await logError("Recovered from redirect", e);
return "Site Moved";
}
finally
{
await logMethodExit();
client.Dispose();
}
}