Using const in string localization doesn't work

Alysson Amaral 156 Reputation points
2021-06-11T12:52:04.247+00:00

I need to use localizition for different languages in a static class, using something similar to this:

public static class ConnectivityHelper 
    {
              const string DEFAULT_ALERT_MESSAGE = Strings.APP_DEFAULT_ALERT_MESSAGE;
              public static void Run(Action action,
                               bool anyConnection = true, 
                               bool shouldAlert = false, 
                               string message = DEFAULT_ALERT_MESSAGE){}
        }

The string message must be constant, the error that appears is:
Error CS0133: The expression being assigned to 'ConnectivityHelper.DEFAULT_ALERT_MESSAGE' must be constant (CS0133).
How can I resolve this?

Developer technologies | .NET | Xamarin
Developer technologies | C#
0 comments No comments
{count} votes

Accepted answer
  1. Michael Taylor 60,161 Reputation points
    2021-06-11T13:50:29.973+00:00

    You cannot use const here. A constant value is literally baked into the source code at compile time. Therefore its value must be known at the point of compilation. Therefore a const value must be assigned a constant expression. A constant expression is any simple expression consisting of other constant expressions which include literals and const values. If the value cannot be calculated at compile time then it cannot be baked into the source code and therefore is illegal.

    Suppose for a moment that Strings.APP_DEFAULT_ALERT_MESSAGE was a const string literal "Message". Then at compilation the compiler would generate code that effectively looks like this:

    const string DEFAULT_ALERT_MESSAGE = "Message";
    

    Any place in code that happens to use the constant would be converted at compile time to the equivalent literal.

    var msg = DEFAULT_ALERT_MESSAGE;  //In code
    var msg = "Message"; //Generated code
    

    This is how constants (in pretty much every language) works.

    In C# we also have readonly. You can google for many articles on the differences but the gist of it is that it is a read only value. If you think of a constant it is a read only value whose identifier is replaced at compilation with the compile time value. A read only value is read only but still refers to the original identifier. At runtime the value is looked up like any other field, except it is read only. From the example earlier

    readonly string DEFAULT_ALERT_MESSAGE = Strings.APP_DEFAULT_ALERT_MESSAGE;
    var msg = DEFAULT_ALERT_MESSAGE;  //In code and what is generated at runtime
    

    Read only is used when you cannot use constants which includes cases where the value may not be known until runtime (example file paths limits) or the type isn't a primitive (which is the only types that can have const values).

    So the correct solution for your scenario is to use readonly instead of const. The biggest restriction on this is that you cannot use readonly values in attribute declarations anymore. Attributes, like constants, are baked into the code at compile time and require all values to be const. Readonly values aren't known until runtime and therefore cannot be used. It is a small price to pay though.

    As an aside you might notice if you work with validation attributes that they all need to be able to pull resources at runtime. Since attributes cannot use readonly values and the resource is a runtime value they all expose a set of properties to allow you to set the resource name and the actual value is retrieved at runtime.

    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.