-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Initial draft of P3 release notes #9832
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
0266626
Initial draft of P3 release notes
KathleenDollard 429a1d6
Apply suggestions from code review
KathleenDollard db5b445
Apply suggestions from code review
KathleenDollard 97d923b
Apply suggestions from code review
KathleenDollard e0ccce6
Apply suggestions from code review
KathleenDollard 89e2f77
Update release-notes/10.0/preview/preview3/csharp.md
KathleenDollard 1d02a86
Merge branch 'dotnet10-p3' into csharp-p3
jamesmontemagno File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,129 @@ | ||
# C# 14 updates in .NET 10 Preview 33 - Release Notes | ||
# C# 14 updates in .NET 10 Preview 3 - Release Notes | ||
|
||
Here's a summary of what's new in C# in this preview release: | ||
|
||
- [Feature](#feature) | ||
- [Extension members](#extension-members) | ||
- [Null-conditional assignment](#null-conditional-assignment) | ||
|
||
C# 14 updates: | ||
|
||
- [What's new in C# 14](https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-14) documentation | ||
- [Breaking changes in C# 14](https://learn.microsoft.com/dotnet/csharp/whats-new/breaking-changes/compiler%20breaking%20changes%20-%20dotnet%2010) | ||
|
||
## Feature | ||
## Extension members | ||
|
||
Something about the feature | ||
Extensions just got even more powerful! In Preview 3, they now support static methods, instance properties, and static properties—expanding the capabilities you already know and love. And this is just the beginning—stay tuned for even more extension support in an upcoming release! | ||
|
||
Expanding extensions to other member types has been a long-standing challenge, driven by two key questions: how to declare them effectively and how to resolve ambiguity when multiple matching signatures exist. Additionally, we aimed to seamlessly support the new syntax for instance members—ensuring that users of instance extension methods never have to worry about whether they were declared with the old or new syntax. After extensive development, we’re bringing these solutions to life! | ||
|
||
Today you may have an extension method that follows the pattern: | ||
|
||
```csharp | ||
public static class Extensions | ||
{ | ||
public static IEnumerable<int> WhereGreaterThan(this IEnumerable<int> source, int threshold) | ||
=> source.Where(x => x > threshold); | ||
} | ||
``` | ||
|
||
The _receiver_ is the parameter prefaced by the `this` keyword - `source` in this case. Property declarations do not have a similar location to declare the receiver. Thus, C# 14 introduces `extension` blocks. These are blocks with a scope that exposes the receiver to its contained members. If we switch the `WhereGreaterThan` extension method to the new syntax and add an IsEmpty property the extension block would be: | ||
|
||
```csharp | ||
public static class Extensions | ||
{ | ||
extension(IEnumerable<int> source) | ||
{ | ||
public IEnumerable<int> WhereGreaterThan(int threshold) | ||
=> source.Where(x => x > threshold); | ||
|
||
public bool IsEmpty | ||
=> !source.Any(); | ||
} | ||
} | ||
``` | ||
|
||
To use these members, you just call them: | ||
|
||
```csharp | ||
var list = new List<int> { 1, 2, 3, 4, 5 }; | ||
var large = list.WhereGreaterThan(3); | ||
if (large.IsEmpty) | ||
{ | ||
Console.WriteLine("No large numbers"); | ||
} | ||
else | ||
{ | ||
Console.WriteLine("Found large numbers"); | ||
} | ||
``` | ||
|
||
Generics are supported and the resolution rules are the same as for extension methods. For example, you could make `WhereGreaterThan` and `IsEmpty` generic: | ||
|
||
```csharp | ||
extension<T>(IEnumerable<T> source) | ||
where T : INumber<T> | ||
{ | ||
public IEnumerable<T> WhereGreaterThan(T threshold) | ||
=> source.Where(x => x > threshold); | ||
|
||
public bool IsEmpty | ||
=> !source.Any(); | ||
} | ||
``` | ||
|
||
The constraint to `INumber<T>` allows the greater than operator to be used. | ||
|
||
Static methods and properties don't have a receiver, so the extension block list the type without a parameter name: | ||
|
||
```csharp | ||
extension<T>(List<T>) | ||
KathleenDollard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
public static List<T> Create() | ||
=> []; | ||
} | ||
``` | ||
|
||
Extension blocks can seamlessly coexist with the extension methods you have today. There's no requirement to switch to the new syntax - both execute in exactly the same way. Just add extension blocks to the static classes that contain your existing extension methods. | ||
|
||
The choice is entirely yours. If you prefer to leave your existing extension methods untouched, you absolutely can. But if you’d rather update your code for a consistent look and take advantage of the new syntax, that option is available too. And with tools like Visual Studio, converting to your preferred form has never been easier! | ||
|
||
You'll see more extensions in upcoming previews, but we'd love to hear your feedback, so join the team and others in the community in the discussion [Extensions](https://github.com/dotnet/csharplang/discussions/8696).. | ||
|
||
## Null-conditional assignment | ||
|
||
Null-conditional assignment assigns a value to a property or field only if the containing instance exists. Imagine you have a code similar to: | ||
|
||
```csharp | ||
public class Customer | ||
{ | ||
public string Name { get; set; } | ||
public int Age { get; set; } | ||
} | ||
|
||
public class UpdateCustomer | ||
{ | ||
public static void UpdateAge(Customer? customer, int newAge) | ||
{ | ||
if (customer is not null) | ||
{ | ||
customer.Age = newAge; | ||
} | ||
} | ||
} | ||
``` | ||
|
||
You can simplify the `UpdateAge` method: | ||
|
||
```csharp | ||
public static void UpdateAge(Customer? customer, int newAge) | ||
{ | ||
customer?.Age = newAge; | ||
} | ||
``` | ||
|
||
If the customer is not null, `Age` will be updated. If customer is null, nothing will happen. | ||
|
||
The IDE will help you by recommending this change via a lightbulb. | ||
KathleenDollard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
We'd love your feedback on this feature so join us and others in the community in the discussion [Null-conditional assignment](https://github.com/dotnet/csharplang/discussions/8676). | ||
======= |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.