[Proposal]: UTF8 literal support for nameof() expressions #6238
Replies: 6 comments 8 replies
-
The |
Beta Was this translation helpful? Give feedback.
-
The proposal uses Integrating some comments from Discord by @sylveon:
That is exactly what I had in mind too and why it looks consistent to me 🙂 Another issue with eg. |
Beta Was this translation helpful? Give feedback.
-
Feels like a lot of this could be handled through some target typing? void Foo([CallerMemberName] ReadOnlySpan<byte> memberName = default) {
ReadOnlySpan<byte> paramName = nameof(memberName);
} |
Beta Was this translation helpful? Give feedback.
-
This was something I thought about too, but after talking with @333fred and @jaredpar, they mentioned that those attributes are just not specced to support UTF8 spans, so enabling that would require more complex changes that they likely wouldn't consider to be worth it. Additionally, there's the point about the LDM deciding to always use |
Beta Was this translation helpful? Give feedback.
-
As detailed in our Readme, new proposals should start as discussions, and only be converted to issues when a member of the LDT indicates to do so. |
Beta Was this translation helpful? Give feedback.
-
What if the compiler allowed |
Beta Was this translation helpful? Give feedback.
-
UTF8 literal support for nameof() expressions
Summary and motivation
This proposal is a small follow up to the UTF8 literal feature. There are many scenarios where developers would want to move to passing UTF8 literals to get better performance and not having to transcode the text at runtime, but the way the feature is currently specced, it would mean that replacing all callsites where today developers are using
nameof
,[CallerMemberName]
,[CallerArgumentExpression]
etc. would not be possible. This would mean that developers would be forced to choose between less error prone code with worse performance (what they have today), or more error prone code (due to hardcoded literals) with faster performance. Having to make a compromise here is not ideal, and this proposal is meant to offer minimal support to solve this issue.Specifically, the proposal is only to enable
nameof
expressions to be used as UTF8 arguments. This would allow developers to get robust code by using thenameof
operator, and callsites currently using[CallerMemberName]
and[CallerArgumentExpression]
could just move tonameof
instead to still have build time checks for the literals, instead of having hardcoded strings.Essentially, the proposal is to allow
u8
to be appended to anameof
expression, like so:This would have the same flexibility as
nameof
today, but with UTF8 support. Roslyn would just lower this exactly the same as it would have had if a literal had been used in place of thatnameof
expression, with theu8
suffix at the end.Use case example
As mentioned in #184 (comment), we have a custom, high-performance, reflection-free ETW logger in the Microsoft Store, which exposes a builder pattern to allow callers to construct their structured events to submit, like so (simplified):
This currently uses
Encoding.UTF8
to get the UTF8 data for those event and field names and build the event metadata. This is not ideal for performance, and we'd like to migrate to just using UTF8 literals. The issue with that is that due to the current design, there would be no way to use them without having to fall back to having hardcoded strings everywhere, which is not great.With the proposed feature instead, we could just drop the attributes and simply do the following:
The .NET runtime also has some examples of where this could be useful. For instance, consider this: https://github.com/dotnet/runtime/blob/2a01ceb2d004a125757a4bb95a9341cc283c5afd/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Utf8Constants.cs#L41-L62. This is exactly the kind of scenario where developers used to hardcode literals before we had the
nameof
operator, and then switched toFoo => nameof(Foo)
when that became available. Having to go back to literals once again just to be able to get UTF8 encoding is not great. This could just be written asFoo => nameof(Foo)u8
instead to avoid the use of hardcoded string literals whenever possible.Detailed design
The design allows using the
u8
suffix on anameof
expression to have it lowered to an UTF8ReadOnlySpan<byte>
. All the same other rules as normal UTF8 literals (see here) apply here. Anameof
expression with theu8
suffix would be lowered exactly the same as a literal with the same content of thenameof
expression, with theu8
suffix.The same conversion rules and other general rules around UTF8 literals would apply here as well, with no changes.
Drawbacks
It's a new, although small, bit of syntax, and it would likely need some mapping in the public code analysis APIs as well.
Alternatives
Force developers to go back to hardcoded strings in all of these scenarios. This works, but it's far from ideal.
Beta Was this translation helpful? Give feedback.
All reactions