The Expression assigned to X must be constant? [duplicate] - c#

This question already has answers here:
CS0133 "The expression being assigned to 'identifier' must be constant" - what's the reason behind that?
(4 answers)
Closed 9 years ago.
I got that error with this code:
const string body = HighPoint; // HighPoint is a string arg passed in to the method
...and was able to work around it by removing the constant:
string body = HighPoint;
...or, of course, assigning a constant value:
const string body = "My Dinner with Andre";
...but is "my way not a very sporting way"? (gratuitous Princess Bride reference)

The keyword const in C# means a compile-time constant. It is different from C++ and C, where the same keyword requires only a run-time const-ness.

const in C# is different from const in C++.
In C++, const a runtime constant. The following operations are valid in C++
i.e
const char *CONST_INFO = "hello world";
CONST_INFO = "goodbye world"; //aok
const int i = SomeMethod(); //aok
C#, on the other hand, is stricter. The constant value must be constant at compile time; no method returns or static class members.
If you need to use a one-off value as a constant (i.e an array, or a method return) you can use the static and readonly modifiers to emulate most of the restrictions the const keyword gives you:
public static readonly string body = HighPoint;
Should compile fine, and you'll still exprience similar restrictions with modifying the value as you would with const

Related

C# string must be a constant [duplicate]

This question already has answers here:
Why does interpolating a const string result in a compiler error?
(6 answers)
Closed 3 years ago.
I was writing this piece of code:
public const int MAJOR_VERSION = 3;
public const int MINOR_VERSION = 3;
public const string VERSION_STRING = $"v.{MAJOR_VERSION}{MINOR_VERSION}";
And, maybe not surprisingly, the compiler was complaining:
"The expression being assigned to VERSION_STRING must be constant"
I understand that const expressions are meant to be propagated by the compiler, but in this particular case, the string can very easily be statically created because it depends only on other constants.
So perhaps someone can explain to me why this is not already a feature of the language?
Or maybe even, why it's silly of me to ask such a question..
Thanks in advance. :)
You have this error because the $ symbol in front of a string is a shortcut for calling String.Format(). String.Format() being a method, its return value cannot be stored in a constant.
When we use const keyword, then the values of string interpolation must be a compile-time constant. Using a string interpolation requires .NET code to execute which can only occur when the application is running, not during compile time.
So instead of const you can use static readonly:
public const int MAJOR_VERSION = 3;
public const int MINOR_VERSION = 3;
public static readonly string VERSION_STRING = $"v.{MAJOR_VERSION}{MINOR_VERSION}";
The string you are trying to set is not a constant value, because it is derived from other variables/constants.
Try static readonly instead
public static readonly string VERSION = $"v.{MAJOR_VERSION}{MINOR_VERSION}";
To explain why the C# team couldn't have made this a compile time feature:
The result of $"{}" or string.Format() can vary at runtime depending on the culture of the machine it's running on at the time.
For example see here that the VERSION is a constant but the resulting strings are different.
const double VERSION = 3.3;
string withDots = String.Format(new System.Globalization.CultureInfo("en-GB"), "{0:N}", VERSION));
// "3.3"
string withCommas = String.Format(new System.Globalization.CultureInfo("fr-FR"), "{0:N}", VERSION));
// "3,3"

Why constants in c# can be declared in methods? [duplicate]

Whenever I have local variables in a method, ReSharper suggests to convert them to constants:
// instead of this:
var s = "some string";
var flags = BindingFlags.Public | BindingFlags.Instance;
// ReSharper suggest to use this:
const string s = "some string";
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
Given that these are really constant values (and not variables) I understand that ReSharper suggest to change them to const.
But apart from that, is there any other advantage when using const (e.g. better performance) which justifies using const BindingFlags instead of the handy and readable var keyword?
BTW: I just found a similar question here: Resharper always suggesting me to make const string instead of string, but I think it is more about fields of a class where my question is about local variable/consts.
The compiler will throw an error if you try to assign a value to a constant, thus possibly preventing you from accidentally changing it.
Also, usually there is a small performance benefit to using constants vs. variables. This has to do with the way they are compiled to the MSIL, per this MSDN magazine Q&A:
Now, wherever myInt is referenced in the code, instead of having to do a "ldloc.0" to get the value from the variable, the MSIL just loads the constant value which is hardcoded into the MSIL. As such, there's usually a small performance and memory advantage to using constants. However, in order to use them you must have the value of the variable at compile time, and any references to this constant at compile time, even if they're in a different assembly, will have this substitution made.
Constants are certainly a useful tool if you know the value at compile time. If you don't, but want to ensure that your variable is set only once, you can use the readonly keyword in C# (which maps to initonly in MSIL) to indicate that the value of the variable can only be set in the constructor; after that, it's an error to change it. This is often used when a field helps to determine the identity of a class, and is often set equal to a constructor parameter.
tl;dr for local variables with literal values, const makes no difference at all.
Your distinction of "inside methods" is very important. Let's look at it, then compare it with const fields.
Const local variables
The only benefit of a const local variable is that the value cannot be reassigned.
However const is limited to primitive types (int, double, ...) and string, which limits its applicability.
Digression: There are proposals for the C# compiler to allow a more general concept of 'readonly' locals (here) which would extend this benefit to other scenarios. They will probably not be thought of as const though, and would likely have a different keyword for such declarations (i.e. let or readonly var or something like that).
Consider these two methods:
private static string LocalVarString()
{
var s = "hello";
return s;
}
private static string LocalConstString()
{
const string s = "hello";
return s;
}
Built in Release mode we see the following (abridged) IL:
.method private hidebysig static string LocalVarString() cil managed
{
ldstr "hello"
ret
}
.method private hidebysig static string LocalConstString() cil managed
{
ldstr "hello"
ret
}
As you can see, they both produce the exact same IL. Whether the local s is const or not has no impact.
The same is true for primitive types. Here's an example using int:
private static int LocalVarInt()
{
var i = 1234;
return i;
}
private static int LocalConstInt()
{
const int i = 1234;
return i;
}
And again, the IL:
.method private hidebysig static int32 LocalVarInt() cil managed
{
ldc.i4 1234
ret
}
.method private hidebysig static int32 LocalConstInt() cil managed
{
ldc.i4 1234
ret
}
So again we see no difference. There cannot be a performance or memory difference here. The only difference is that the developer cannot re-assign the symbol.
Const fields
Comparing a const field with a variable field is different. A non-const field must be read at runtime. So you end up with IL like this:
// Load a const field
ldc.i4 1234
// Load a non-const field
ldsfld int32 MyProject.MyClass::_myInt
It's clear to see how this could result in a performance difference, assuming the JIT cannot inline a constant value itself.
Another important difference here is for public const fields that are shared across assemblies. If one assembly exposes a const field, and another uses it, then the actual value of that field is copied at compile time. This means that if the assembly containing the const field is updated but the using assembly is not re-compiled, then the old (and possibly incorrect) value will be used.
Const expressions
Consider these two declarations:
const int i = 1 + 2;
int i = 1 + 2;
For the const form, the addition must be computed at compile time, meaning the number 3 is kept in the IL.
For the non-const form, the compiler is free to emit the addition operation in the IL, though the JIT would almost certainly apply a basic constant folding optimisation so the generated machine code would be identical.
The C# 7.3 compiler emits the ldc.i4.3 opcode for both of the above expressions.
As per my understanding Const values do not exist at run time - i.e. in form of a variable stored in some memory location - they are embeded in MSIL code at compile time . And hence would have an impact on performance. More over run-time would not be required to perform any house keeping (conversion checks / garbage collection etc) on them as well, where as variables require these checks.
const is a compile time constant - that means all your code that is using the const variable is compiled to contain the constant expression the const variable contains - the emitted IL will contain that constant value itself.
This means the memory footprint is smaller for your method because the constant does not require any memory to be allocated at runtime.
Besides the small performance improvement, when you declare a constant you are explicitly enforcing two rules on yourself and other developers who will use your code
I have to initialize it with a value right now i can't to do it any place else.
I cannot change its value anywhere.
In code its all about readability and communication.
A const value is also 'shared' between all instances of an object. It could result in lower memory usage as well.
As an example:
public class NonStatic
{
int one = 1;
int two = 2;
int three = 3;
int four = 4;
int five = 5;
int six = 6;
int seven = 7;
int eight = 8;
int nine = 9;
int ten = 10;
}
public class Static
{
static int one = 1;
static int two = 2;
static int three = 3;
static int four = 4;
static int five = 5;
static int six = 6;
static int seven = 7;
static int eight = 8;
static int nine = 9;
static int ten = 10;
}
Memory consumption is tricky in .Net and I won't pretend to understand the finer details of it, but if you instantiate a list with a million 'Static' it is likely to use considerably less memory than if you do not.
static void Main(string[] args)
{
var maxSize = 1000000;
var items = new List<NonStatic>();
//var items = new List<Static>();
for (var i=0;i<maxSize;i++)
{
items.Add(new NonStatic());
//items.Add(new Static());
}
Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().WorkingSet64);
Console.Read();
}
When using 'NonStatic' the working set is 69,398,528 compared to only 32,423,936 when using static.
The const keyword tells the compiler that it can be fully evaluated at compile time. There is a performance & memory advantage to this, but it is small.
Constants in C# provide a named location in memory to store a data value. It means that the value of the variable will be known in compile time and will be stored in a single place.
When you declare it, it is kind of 'hardcoded' in the Microsoft Intermediate Language (MSIL).
Although a little, it can improve the performance of your code. If I'm declaring a variable, and I can make it a const, I always do it. Not only because it can improve performance, but also because that's the idea of constants. Otherwise, why do they exist?
Reflector can be really useful in situations like this one. Try declaring a variable and then make it a constant, and see what code is generated in IL. Then all you need to do is see the difference in the instructions, and see what those instructions mean.

The Expression assigned to X must be constant

I'm having this problem and searching for solutions, but didn't find a situation similar to mine.Here's what I have:
in a class file X.cs:
namespace BlaBla{
public class X{
public const string foo = "foo";
// other code
}
public class Y{
public const int bar = 0;
}
}
and in some other class, I'm writing:
private const string someString = X.foo + Y.bar + "";
it keeps giving me a compile error:
The Expression assigned to someString must be constant
although they are both constant! when I remove Y.bar the error is removed and I dont know why. Any help ?
You're using the const keyword wrong. You probably want to define someString as:
private readonly someString = X.foo + Y.bar;
When a variable is marked as const they are compiled in to the assembly and then optimised. While Y.bar is defined as const, you're implicitly invoking its ToString() method which makes it not constant.
You're including a conversion from int to string. Even though the int is a constant, the conversion isn't considered a constant expression.
You can demonstrate that more simply:
class Test
{
const int X = 10;
const string Y = "X: " + X;
}
See section 7.19 of the C# specification for more details about what counts as a constant expression.
The expression looks constant, but it requires evaluation so that value can be figured out.

function returning a const value

I have a following function which accepts a enum value and based upon the enum value returns a constant value(which is in a different class). Now i get a "Constant initializer missing" Error.
public const int Testfunction(TESTENUM TestEnum)
{
switch(TestEnum)
{
case TestEnum.testval1:
return testclass.constvalue;
case TestEnum.testVal2:
return testclass.constvalue1;
case TestEnum.testVal3:
return testclass.constvalue2;
}
}
how exactly the function's return type would be? (I am using object return type and this does not throw any error)
Is there any other option to achieve the same?
What's happening here is the compiler thinks that you are trying to declare a public constant integer field named Testfunction, and is extremely surprised to discover that there is no = 123; following the identifier. It's telling you that it expected the initializer.
There are a number of places in the C# compiler where the development team anticipated that C and C++ users would use a common C/C++ syntax erroneously. For example, there's a special error message for int x[]; that points out that you probably meant int[] x;. This is an example of another place where the compiler could benefit from a special-purpose error message that detects the common mistake and describes how to fix it. You might consider requesting that feature if you think it's a good one.
More generally, "const" in C# means something different than it means in C or C++. C# does not have the notion of a "const function" that does not mutate state, or a "const reference" that provides a read-only view of potentially-mutable data. In C# "const" is only used to declare that a field (or local) is to be treated as a compile-time constant. (And "readonly" is used to declare that a field is to be written only in the constructor, which is also quite useful.)
Removing "const" keyword from your function return type should solve the problem
It should be like this
public int Testfunction(TESTENUM TestEnum)
{
...
Return type cannot be declared constant
.NET methods cannot return const any type..
The const keyword is invalid there: remove it.
The most likely working code:
public static class TestClass
{
public const int constValue1 = 1;
public const int constValue2 = 2;
public const int constValue3 = 3;
}
enum TestEnum
{
testVal1, testVal2, testVal3
}
public int TestFunction(TestEnum testEnum)
{
switch (testEnum)
{
case TestEnum.testVal1:
return TestClass.constValue1;
case TestEnum.testVal2:
return TestClass.constValue2;
case TestEnum.testVal3:
return TestClass.constValue3;
}
return 0; // all code paths have to return a value
}
First, according to const (C# Reference):
The const keyword is used to modify a declaration of a field or local variable. It specifies that the value of the field or the local variable is constant, which means it cannot be modified.
In C#, const is only used as a modifier of a field (like TestClass.constValue1) or local variable, not suitable for a function return type.
So you are from the great C/C++ kingdom. Thinking with my very limited knowledge to C/C++, const return types in C/C++ is only meaningful with pointers...
// C++ code
const int m = 1;
// It returns a pointer to a read-only memory
const int* a(){
return &m;
}
But unless you are using unsafe code, there is no pointer in C#. There are only value types (like int/DateTime/TestEnum/structs) and reference types (like string/classes). There are a lot more to read about on the web.
So as int is a value type in C#, when you returns it, it gets copied. So even if you are returning a "constant int" the returned value is not a constant and modifying the return value will not "change the constant and cause a SegFault".
Well, I forgot to answer your questions...
How exactly the function's return type would be? (I am using object return type and this does not throw any error)
Like what I showed in the code above, int.
const int blah = 1 only declares a variable/field blah of type int which one must not modify it (by doing blah = 2). In C# const int is not a type.
Is there any other option to achieve the same?
Well... I think I don't actually need to answer this...

How can this not be a constant value?

I know this is probably just a terminology mismatch but if i'm not mistaken i believe c# is? unless i'm missing something obvious??
...
private const uint URL_COUNT = 18;
private string[] _urls;
public Redirector()
{
this._urls = new string[URL_COUNT];
...
}
...
Results in “A constant value is expected “ and underlines URL_COUNT in the array definition??
Whats URL_COUNT if it isn’t a const -ant value?!?!
EDIT
Phew, i thought for a second then i was going mad. I'm glad no one could repro this as that means it's just a local thing.
Thanks for your help guys.
This will only fail to compile when you supply both the dimension lengths and an array initializer. For example:
this._urls = new string[URL_COUNT];
will be fine, but:
this._urls = new string[URL_COUNT] { "One", "Two" };
will not. The latter requires a constant expression. Note that a const variable is not a constant expression, just a constant value. From the C# specification (3.0) par 12.6:
When an array creation expression
includes both explicit dimension
lengths and an array initializer, the
lengths must be constant expressions
and the number of elements at each
nesting level must match the
corresponding dimension length.
It is a constant and should work fine. The following code compiled fine for me with the C# 3 compiler:
using System;
class Foo
{
private const uint URL_COUNT = 18;
private string[] _urls;
public Foo()
{
this._urls = new string[URL_COUNT];
}
}
This works too, without any complaints from the compiler.
class Foo {
private const uint URL_COUNT = 18;
private readonly string[] _urls = new string[URL_COUNT];
}

Categories

Resources