I'm writing unit tests (MSTest) in C# 6.0 and I noticed something strange in the way the compiler handles string interpolation in attributes.
Why does this work:
[TestCategory(nameof(MyClass) + "-UnitTest")]
When this doesn't?
[TestCategory($"{nameof(MyClass)}-UnitTest")]
Ignoring the fact that this might not be a great way to categorize my tests; I'm curious why the compiler allows one and not the other.
Beginning with C# 10, you can use string interpolation to initialize a constant string. All expressions used for placeholders must be constant strings. In other words, every interpolation expression must be a string, and it must be a compile time constant.
C# string interpolation is used to format and manipulate strings. This feature was introduced in C# 6. Using string interpolation, we can use objects and expressions as a part of the string interpolation operation. C# string interpolation is a method of concatenating, formatting and manipulating strings.
String interpolation is common in many programming languages which make heavy use of string representations of data, such as Apache Groovy, Julia, Kotlin, Perl, PHP, Python, Ruby, Scala, Swift, Tcl and most Unix shells.
Strings that contain references to variables or expressions are called interpolated strings. When you use interpolated strings, the embedded expressions and variables are evaluated and the result is inserted into the string. The act of inserting data into a string is called string interpolation.
When the compiler encounters an interpolated string it immediately converts it into a call to String.Format
so...
[TestCategory($"{nameof(MyClass)}-UnitTest")]
Becomes...
[TestCategory(string.Format("{0}-UnitTest", nameof(MyClass)))]
Attributes require that their arguments be constant expressions but the above expression will not be evaluated until execution time hence the error...
CS0182 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type...
You know all the information is available at compile time but the compiler is not smart enough to figure it out.
nameof
works a bit differently than interpolated strings because it is evaluated at compile-time so there is no error.
Interpolated strings are not constant values. The value is determined at runtime, even though in your case all inputs can be calculated at compile time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With