8

I know that I can create new constant strings by concatenating other constant strings:

const string a = "A";
const string ab = a + "B";

Is it somehow possible to create a constant string based on a constant int? For example, the following won't compile:

const int Dpi = 300;
const string DeviceInfo = "<DeviceInfo><Dpi>" + Dpi + "</Dpi></DeviceInfo>";

The expression assigned to MyClass.DeviceInfo must be constant.

I know that I could work around this by

  1. making Dpi a string instead of an int (and int.Parseing it when I need the int value),
  2. adding a second string constant DpiString (and, thus, violating DRY), or
  3. making DeviceInfo a static readonly field instead of a const field.

I'm going to go with option 3, but, out of curiosity, I was wondering if there is some other option that I missed...

3
  • 2
    The current expression isn't a const expression because converting an int to string will use a format provider and that is only available at runtime Commented Dec 2, 2017 at 10:12
  • So string + object uses a culture-sensitive conversion for object? Good to know, the documentation is unfortunately not very clear on that. Commented Dec 2, 2017 at 10:23
  • Just violate DRY, and put in a test case to make sure the values don't get out of sync. Commented Mar 7, 2019 at 11:38

3 Answers 3

10

No, string constants cannot be expressions that are evaluated at runtime.

The following conversions are permitted in constant expressions:

  • Identity conversions
  • Numeric conversions
  • Enumeration conversions
  • Constant expression conversions
  • Implicit and explicit reference conversions, provided that the source of the conversions is a constant expression that evaluates to the null value.

Other conversions including boxing, unboxing and implicit reference conversions of non-null values are not permitted in constant expressions.

Converting an int to a string falls in the "other conversions" which are not permitted, since this requires a call to the ToString() method.

In point of fact, the conversion requires a call to int.ToString() which is defined to use the G10 number format. This depends on the current culture's NumberFormatInfo.NegativeSign so could in principle change. I'm not aware of any default culture which uses anything for the negative sign other than the \u002d hyphen-minus character, but you could certainly set it at runtime to something else if you want to see the world burn.

Sign up to request clarification or add additional context in comments.

5 Comments

So, essentially, you are saying that string + object performs a culture-sensitive conversion of object, which, therefore, cannot be performed at compile-time.
@Heinzi, No, I am saying that you can't do it because it's not allowed by the standard, and therefore the compiler doesn't contain the required logic to make it work. All features start out not existing - to make this work would require someone to write code to make it work, they haven't so it doesn't!
In point of fact, int.ToString() is defined to use the current culture: msdn.microsoft.com/en-us/library/6t7dwaa5(v=vs.110).aspx but it could have been defined differently.
Interesting - the output string can actually depend on the current culture - if it is negative the current culture's NumberFormatInfo.NegativeSign will be used.
@Heinzi Yes, it surprised me!
3

You can't do that with const. But what is your main concern here? Do you want to make sure the value will never change, or do you want it to be available at compile time?

If you want to make sure it will never change, you can use either of these:

  1. Readonly field
  2. Readonly property with a field, both encapsulated in a singleton class.
  3. Readonly property concatenating strings at run-time
  4. A static readonly field

But in some use-cases you may want to have the value available at compile-time. In that case you have to make your integer a const string, as you've described in your options 1 and 2.

Comments

0

There are two options to handle this case:

1) If Dpi is always same (since it is a constant) then there is no need concat two different Strings. You can directly write the value in the string itself.

2) If Dpi is not a constant value. Then you should try using String.format.

2 Comments

1) violates DRY, 2) won't work either.
You can also try to create a model class for Device Info and serialize it into XML later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.