# 7 New Features of C# 11

Microsoft released C# 11 on November 2022. C# 11 has great new features and enhancements. You will like these features, especially *Required Member* and *Raw String Literals.*

You can find the source code for this post on my [GitHub repository](https://github.com/ibrahimuludag/CSharp11).

Let's discover C# 11.

# 1 - Raw String Literals

I have been waiting for this feature for a long time. No more escaping strings.

You can create multiline strings as below.

```csharp
string rawStringLiteralDelimiter = """"
    Raw string literals are delimited 
    by a string of at least three double quotes,
    like this: """
    """";
```

A raw string literal starts with at least three double-quote (""") characters. It ends with the same number of double-quote characters. Typically, a raw string literal uses three double quotes on a single line to start the string, and three double quotes on a separate line to end the string.

```csharp
string singleLine = """Friends say "hello" as they pass by.""";
```

Embedding XML and JSON string is a piece of cake now.

```csharp
string embeddedXML = """
       <element attr = "content">
           <body style="normal">
               Here is the main text
           </body>
           <footer>
               Excerpts from "An amazing story"
           </footer>
       </element >
       """;

string jsonString = """
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "DatesAvailable": [
    "2019-08-01T00:00:00-07:00",
    "2019-08-02T00:00:00-07:00"
  ],
  "TemperatureRanges": {
    "Cold": {
      "High": 20,
      "Low": -10
    },
    "Hot": {
      "High": 60,
      "Low": 20
    }
            },
  "SummaryWords": [
    "Cool",
    "Windy",
    "Humid"
  ]
}
""";
```

The following examples demonstrate the compiler errors reported based on these rules:

```csharp
// CS8997: Unterminated raw string literal.
var multiLineStart = """This
    is the beginning of a string 
    """;

// CS9000: Raw string literal delimiter must be on its own line.
var multiLineEnd = """
    This is the beginning of a string """;

// CS8999: Line does not start with the same whitespace as the closing line
// of the raw string literal
var noOutdenting = """
    A line of text.
Trying to outdent the second line.
    """;
```

# 2 - Required Members

You can add the **required** modifier to properties and fields to enforce constructors and callers to initialize those values.

Previously, I was using constructors to ensure obligatory properties were set. However, this method increased the complexity and maintainability of my code. Now, with the help of the **required** modifier, this is easier.

```csharp
public class Book
{
    public required string Title { get; set; }
    public required string Author { get; set; }
    public int? Pages { get; set; }
}

// This will compile
var solito = new Book { Author = "Javier Zamora", Title = "Solito: A Memoir" };

// This will not compile
var solitoError = new Book { Author = "Javier Zamora" };
```

You will also see the **required** properties on IntelliSense.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673812798263/c8a76c0d-dcaf-44a6-b08e-6c04e0b1136a.png align="center")

# 3 - Auto Default Structs

The C# 11 compiler ensures that all fields of a **struct** type are initialized to their default value as part of executing a constructor.

```csharp
public struct Coordinate
{
    public double Longitude { get; set; }
    public double Latitude { get; set; }
    
    public override string ToString()
    {
        return $"Longitude : {Longitude}, Latitude : {Latitude}";
    }
}

Console.WriteLine(new Coordinate());

// Output is as below
// Longitude : 0, Latitude : 0
```

# 4 - File Local Type

Beginning in C# 11, you can use the **file** access modifier to create a type whose visibility is scoped to the source file in which it is declared. This feature helps source generator authors avoid naming collisions.

# 5 - Generic Attributes

You can declare a generic class whose base class is System.Attribute. This feature provides a more convenient syntax for attributes that require a System.Type parameter.

```csharp
public class GenericAttribute<T> : Attribute {
    public T Name { get; private set; }

	public GenericAttribute(T name)
	{
		Name = name;
	}
}

[Generic<int>(10)]
public class GenericClass1
{
}

[Generic<string>("Hello World")]
public class GenericClass2
{
}


// Below will not compile
[Generic<T>()]
public class GenericClass3<T>
{
}
```

# 6 - List Patterns

In previous versions of C#, pattern matching was introduced. In C#11 pattern matching was extended to use lists and arrays.

```csharp
int[] numbers = { 1, 2, 3 };

Console.WriteLine(numbers is [1, 2, 3]);  // True
Console.WriteLine(numbers is [1, 2, 4]);  // False
Console.WriteLine(numbers is [1, 2, 3, 4]);  // False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]);  // True

// Discard pattern "_"
// Slice pattern ".."
Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]);  // True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]);  // True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]);  // False
Console.WriteLine(new[] { 1 } is [1, 2, ..]);  // False

Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]);  // True
Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]);  // False
Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]);  // True

Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]);  // True
Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]);  // True
Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]);  // False
```

# 7 - Utf8 String Literals

You can specify the **u8** suffix on a string literal to specify UTF-8 character encoding. If your application needs UTF-8 strings for HTTP string constants or similar text protocols, you can use this feature to simplify the creation of UTF-8 strings.

```csharp
string s1 = "hello"u8;             // Error
var s2 = "hello"u8;                // Okay and type is ReadOnlySpan<byte>
ReadOnlySpan<byte> s3 = "hello"u8; // Okay.
byte[] s4 = "hello"u8;             // Error - Cannot implicitly convert type 'System.ReadOnlySpan<byte>' to 'byte[]'.
byte[] s5 = "hello"u8.ToArray();   // Okay.
Span<byte> s6 = "hello"u8;         // Error - Cannot implicitly convert type 'System.ReadOnlySpan<byte>' to 'System.Span<byte>'.
```

# Conclusion

These are several features of C# 11. If you want to learn more, you can go to ["What's new in C# 11"](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11).

Happy Coding!

# References

* [https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11)
    
* [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#struct-initialization-and-default-values](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct#struct-initialization-and-default-values)
    
* [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/file](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/file)
    
* [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns)
    
* [https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings)
    
* [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/utf8-string-literals](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/utf8-string-literals)
