SoFunction
Updated on 2025-03-06

Quickly master C# 6.0 knowledge points in thirty minutes

1. Read-only auto-properties

Before C# 6, we built read-only automatic properties:

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

Principle analysis:When the compiler generates a set accessor, its modifier is private. From the above, we can see that the so-called read-only is only for outside the class, and the attribute value can still be modified at will within the class.

C# 6 provides true read-only automatic attributes, written as follows:

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

Principle analysis:First, the compiler will generate a readonly private field and the get accessor returns the value of the field. From the above, we can see that the read-only automatic property can only be assigned a value in the constructor.

2. Automatic property initializers (Auto-Property Initializers)

In the past, we could only write the assignment operation of automatic attributes in methods, such as constructors:

 public Student(string firstName, string lastName)
 {
 FirstName = firstName;
 LastName = lastName;
 }

But in C# 6 we can treat the assignment operation as part of the declaration, as shown below:

 public string FirstName { get; set; } = "Corleone";
 public string LastName { get; set; } = "Mike";

Remark:In fact, C# 6 and previous versions are the same as the assignment operation in the end, but the latter is obviously more concise and intuitive, so this is a good syntax sugar.

3. Expression-bodied function members

A new syntax provided in C# 6: For method bodies with only one statement, they can be abbreviated as expressions. As in the following two situations:

1. Methods

 public Student Create() => new Student();

 

Equivalent to:

 public Student Create()
 {
  return new Student();
 }

2. Read only properties

 public string FullName => ("{0},{1}", FirstName, LastName);

Equivalent to:

public string FullName
 {
  get
  {
   return ("{0},{1}", FirstName, LastName);
  }
 }

Principle analysis:After compilation, the above expression will generate the most primitive method body and accessor. It is worth mentioning that the function expression body and Lambda are two similar but different things, the function table.

The Exegetic style can only carry one sentence and cannot contain the return keyword, but Lambda can carry statement blocks and contain keywords.

4. Use static

A new syntax in C# 6: When using a static member of a type, its type can be omitted, as follows:

 using static ;  // Import the corresponding member type first public bool IsNull(string str) => IsNullOrEmpty(str); 

Equivalent to:

 public bool IsNull(string str) => (str);

Summarize:The purpose of this syntax sugar is to make the code more concise, but this should be differentiated in usage scenarios, such as: Mathematical calculations (Math class) Using this syntax sugar can indeed make the code simpler and more readable

sex, but if you import too many types somewhere, it will not only not improve reading quality but will increase reading difficulty, because you don’t know which type these members belong to. Also, if the type itself has a member of the same name, it will be overridden by using the type member.

Notice:The syntax sugar used by static is not applicable to the extension method, because the design concept of the extension method is to not modify existing code and can only be used within a certain range, so in special cases, it is necessary to

It is used as a static method, so it is wise to use class name calls.

5. Null-conditional operators

Anyone with a little experience knows that during the Coding process, it is often necessary to judge whether the value of a variable is null. There are many operations like this if-else. This makes the code look very unconcise, and fortunately, C#6 provides a solution:

 var student = new Student();
 var firstName = student?.FirstName;

Equivalent to:

var student = new Student();

 string firstName = null;
 if (student != null)
 {
  firstName = ;
 }

How to use:Just replace the member access character . to ?. . If ?. is null on the left, the result of the entire operator is also null, otherwise the result of the operator is equal to its member value. If the member type is a value

Types The type returned by the entire expression is the nullable type of the corresponding type, such as:

 int? age = student?.Age;

Principle analysis:?. After compilation, it is the if or ternary operator. Non-assignment operations (such as call) will be compiled into if, and assignment operations will generally be compiled into ternary operators.

6. String Interpolation

A new syntax is provided in C# 6 to build formatted strings, such as:

 var fullName = $"{},{}";

Equivalent to:

 var fullName = ("{0},{1}", , );

How to use:Just put the $ symbol before the string and fill in the expression (field, method, Lambdad...) in the braces.

Remark:

1. String interpolation syntax supports all previous string formatting settings, such as:

 ($"Average grade:{:F2}");

Note:Because : is always interpreted by the compiler as a separator of expression and string format, if there are conditional operators in the expression, we need to use brackets to force compilation and parse it into the current context.

The meaning of expression. like:

 ($"Average grade:{( > 80 ?  : 0):F2}");

2. String interpolation syntax can be nested, such as:

 var score = $"My grades in each subject:{ $"math:{};English:{};"}";

Principle analysis:$"xxx{expression1}xxx{expression2}..." After compilation, it is ().

7. Exception filters

A new feature in C# 6 is the exception filter, which allows us to apply the Catch clause at the right time, such as:

try
 {
  throw new WebException("Request timed out..", );
 }
 catch (WebException webEx) when ( == )
 {
  // Exception handling
 }

How to use:try-catch() when()。

Summarize:The biggest highlight of exception filters is that they can not lose the stack information of the exception trigger point when used properly, which is crucial for program error troubleshooting. In addition, it has many interesting uses, you can check it online.

8. Nameof Expressions

The function of the nameof expression is to get member names, such as throwing exceptions:

public string FullName(Student student)
 {
  if (student == null)
   throw new ArgumentNullException(nameof(student));

  return $"{},{}";
 }

advantage:nameof expression It can understand members, and when members are renamed, the nameof expression is also renamed, and constant string notation does not have such an advantage.

shortcoming:The nameof expression generates an incompletely qualified name. If you need a fully qualified name, nameof will not help you.

Principle analysis:nameof is the name of its (member) string during compilation, that is, it is the manifestation of a constant string after compilation.

9. Use Await in Catch and Finally blocks

C# 5 provides async and await to make asynchronous programming extremely easy, but they also have limitations: await cannot be used in catch and finally blocks. But this problem has been solved in C# 6, such as:

public static async Task<string> MakeRequestAndLogFailures()
 {
  await logMethodEntrance();
  try
  {
   // ....
   var responseText = await streamTask;
   return responseText;
  }
  catch ( e) when (("301"))
  {
   await logError("Recovered from redirect", e);
   return "Site Moved";
  }
  finally
  {
   await logMethodExit();
  }
 }

10. Index Initializers

This function is nothing new. In fact, it has supported collection/dictionary initializers before, such as:

var list = new List<string>()
 {
  "Mike",
  "Jim"
 };
 
 var dic = new Dictionary<int, string>()
 {
  { 20, "Mike" },
  { 30, "Jim" }
 };

In C# 6, the dictionary initializer supports new writing methods, such as:

 var dic = new Dictionary<int, string>()
 {
  [20] = "Mike",
  [30] = "Jim"
 };

Summarize:No special usage has been found.

11. Improved overload resolution - compiler (Improved overload resolution)

This is not a new syntax, because it is just an improvement in the compiler. The reason I mentioned it is to let everyone know that there is such a thing. The previous compilers could not recognize (Func<Task>()), as follows:

static Task DoThings()
 {
  return (0);
 }
 
 (DoThings); // The method code is omitted here...

The above code cannot be compiled under the old version of the compiler, but can be compiled and passed in the new version of the compiler.

Remark:It is worth mentioning that the new version of the compiler only recognizes (Func<Task>()), but (Action) still cannot recognize it. In general, this function is not very useful to us.

It's better to write back the Lambda expression obediently.

Summarize

The above is the entire content of this article. I hope the content of this article will be of some help to your study or work. If you have any questions, you can leave a message to communicate. Thank you for your support.