3

[TL;DR] why const string SomeConstString = SomeEnum.OneEnumValue.ToString(); is not allowed in C# even if it can be processed in compile-time?

Below attribute definition is from Azure WebJobs SDK;

[AttributeUsage(AttributeTargets.Parameter)] [DebuggerDisplay("{DebuggerDisplay,nq}")] public sealed class ServiceBusTriggerAttribute : Attribute { private readonly string _queueName; private readonly string _topicName; private readonly string _subscriptionName; /// <summary> /// Initializes a new instance of the <see cref="ServiceBusTriggerAttribute"/> class. /// </summary> /// <param name="queueName">The name of the queue to which to bind.</param> public ServiceBusTriggerAttribute(string queueName) { ... } 

And the usage of the code is as below;

public static void GetBapulActivityFromTopic( [ServiceBusTrigger("SomeConstString")] BrokeredMessage message, TextWriter log) { ... } 

In above usage, I understand that "SomeConstString" should be const string type as the value has to be compile-time constant.

But why SomeEnum.OneEnumValue.ToString() cannot be a compile-time constant?

3 Answers 3

6

Even though SomeEnum.OneEnumValue is a const, invoking a method on it is not a compile-time constant expression according to C# Language Specification. Here is a partial list of what is allowed:

  • Literals (including the null literal).
  • References to const members of class and struct types.
  • References to members of enumeration types.
  • References to const parameters or local variables
  • Parenthesized sub-expressions, which are themselves constant expressions.

Method invocations are not allowed in constant expressions. See section N.19 for a complete list.

If you are using C# 6, you can use nameof operator instead, which produces a compile-time constant:

const string SomeConstString = nameof(SomeEnum.OneEnumValue); 
Sign up to request clarification or add additional context in comments.

Comments

3

Because Enum.ToString() is just a regular method call. It contains it's own logic inside. For example, if will check if given enum has [Flags] attribute and if yes - will convert enum value to string in a different way. C# compiler won't call arbitrary methods at compile time, so it cannot be compile-time constant.

And anyway it't not a very good idea to use enums in this case. For example, azure queue name can start with a number and contain dashes (as I remember), while enum cannot. Maybe today you don't use such queue names but who knows what will happen tomorrow. So it's better just define static class with public constants.

Comments

2

C# (and the CLR/.NET) does not have the notion of constexpr that C++ does, unfortunately. Because the CLR does not support it means that the compiler cannot make that assumption, hence it fails.

But FWIW, the CLR does not process your expression at compile-time, it will always be evaluated at runtime.

The workaround, in modern C#, is to use constructs like nameof and T4.

More specifically, SomeEnum.OneEnumValue itself is a field-accessor, and the .ToString() is a virtual instance method. Hypothetically another CLR environment could legally add some trickery that makes the ToString() method not predictable at all (e.g. taking localization/thread culture into consideration), so then it demonstrably would not be able to be processed at compile-time at all.

Another counter-argument: what if SomeEnum were to be defined in a separable assembly (.dll) file completely? The linking between assemblies only happens at runtime, so if you were to replace the assembly that contained SomeEnum then the runtime cannot assume .ToString() would return the same value.

Also, note that static readonly and const are not equivalent:

If you have AssemblyA that references AssemblyB, and AssemblyA uses a const String defined in AssemblyB, then AssemblyA will actually contain a copy of the const value from AssemblyB, even if AssemblyB is replaced at runtime. That's part of the nature of const in the CLR.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.