

Caller Argument Expressions – A Look at New Language Features in C# 10
source link: https://blog.jetbrains.com/dotnet/2021/11/04/caller-argument-expressions-in-csharp-10/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Caller Argument Expressions – A Look at New Language Features in C# 10
Welcome to the second part of our series, where we take a closer look at the new C# language features the .NET team has implemented, and how ReSharper and Rider make it easy to adopt them in your codebase. Welcome to C# 10 and .NET 6!
In this series, we are looking at:
- File-Scoped Namespaces
- Caller Argument Expressions
- Global Usings
- Interpolated String Improvements
- Lambda Improvements
- … and more to be announced
In this post we will discuss all relevant aspects of Caller Argument Expressions and where they’re helping. Have fun and be amazed! 😃
Caller Argument Expression
The new CallerArgumentExpressionAttribute
joins the family of existing attributes to determine caller information, like the member name or file path, without using reflection. This can then be used to provide better information about the origin of an error. The new attribute allows capturing an expression passed for a parameter as a simple string:
public static void Main(string[] args) { // What you call Assert(args.Length != 1); // What gets compiled Assert(args.Length != 1, "args.Length != 1"); } public static void Assert( bool condition, [CallerArgumentExpression("condition")] string conditionExpression = default) { if (!condition) throw new Exception($"Condition failed: {conditionExpression}"); }
This opens up great possibilities for both library and infrastructure code, including getting rid of using Expression<Func<T>>
for the sole purpose of getting the name of the passed expression and the involved reflection overhead.
One of my personal favorites that benefit from the new attribute is the NotNull<T>(string message = null)
extension method, which asserts an object to be not null
as follows:
static void M(Person person) { var addresses = person.NotNull().Addresses; var relatives = person.Relatives.NotNull(); } static void NotNull<T>(this T obj, string message = null)
Previously, the best you could achieve without providing a message was to include the typeof(T).FullName
in the exception message. Now you can add another parameter that captures the expression on which the method was called. With a few Roslyn nullability annotations, you can improve the assertion method as follows:
[return: NotNull] public static T NotNull<T>( [NotNull] this T? obj, string? message = default, [CallerArgumentExpression("obj")] string? parameterName = default) where T : class { return obj ?? throw new ArgumentNullException(parameterName, message); }
With this method, you can flexibly assert expressions for being not null
. You can let the CallerArgumentExpression
attribute work its magic, or you can pass a custom message. For the latter, ReSharper and Rider will even offer code completion to use the assigned variable name instead of the invoked expression:
Of course, ReSharper and Rider 2021.3 come with a set of new inspections to help you use the attribute in the correct manner. For instance, on the call site you will get a warning when a value is explicitly passed, which is most likely unintended:
On the method definition, you’ll be guarded against accidentally making it self-referential …
… from providing an incorrect parameter name …
… and from conflicts with other compiler service attributes:
An issue that remains, for now, is the inability to reference parameters with the nameof
operator to avoid magic strings. Make sure to give the issue a vote if it’s important to you! Until then, ReSharper and Rider have you covered and will provide code-completion for valid parameter names but also update parameter references when you rename them:
We were curious and asked people what they’re using the caller-information attributes for. Besides exception messages, validation, and INotifyPropertyChanged
variations, we’ve also found DebounceMonitoring as a very interesting project:
Download ReSharper 2021.3 EAP or check out Rider 2021.3 EAP to start taking advantage of C# 10 in the best possible way. We’d love to hear your thoughts!
Recommend
-
35
Android: Your Users as Caller ID Set up your app to display user info in the Android calling app. Aug 27, 2019 ...
-
17
There is an unnecessary drama unfolding on Twitter on “the war” between connectionists and symbolists. This drama is absurd and perpetuated by people whose relevance exists only in the discussion of the “difference” and th...
-
12
Trace caller's source location in the stable Rust Reading Time: < 1 minute Hello folks, In this blog, I will be introducing a feature to track source location of caller of a function.In one of the Rust...
-
8
Description In this quick video, Cecil and Jayme will teach us about the new target-typed new expres...
-
8
ICYMI C# 8 New Features: Switch ExpressionsIn the first part of this series on what was introduced in C# 8, we’re going to take a look at switch expressions. Switch expressions allow you to write fewer lines of code when making use of...
-
32
.NET Tools How-To's File-Scoped Namespaces – A Look at New Language Features in C#...
-
8
.NET Tools How-To's Global Usings – A Look at New Language Features in C# 10...
-
6
Generating argument expressions for minimal APIs This is the fourth post in the series: Behind the scenes of minimal APIs.
-
6
Generating argument expressions for minimal APIs (continued) Behind the scenes of minimal APIs - Part 5 ...
-
5
C# 11.0 new features: newlines in string interpolation expressions
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK