The Expression assigned to X must be constant - c#

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.

Related

why can't I define a non printable character as constant c#

private const string requireNonPrintableChar = new string('\x0005', 1);
I do not expect this value to change. I was told once upon a time it's good practise to use const for values you don't expect to change.
However msbuild is saying:
"Error 1 The expression being assigned to requireNonPrintableChar' must be constant"
am assuming that char doesn't count as a const but why?
The msdn says it can be a string which I believe it is.
Simply do:
private const string requireNonPrintableChar = "\x0005";
new string('\x0005', 1) is an expression that does get evaluated to a string, but it is not a compile-time constant, and const fields can only be assigned values which can be evaluated at compile time.
A constant has to be defined directly. You can't use functions to get your const value.
Instead of doing this
const string MY_CONST = test();
static string GetValue()
{
return "Hello";
}
You should do this
const string MY_CONST = "Hello";
If you want to use method initialization you could use static readonly like this
private static readonly string requireNonPrintableChar = new string('\x0005', 1);
Source
You can do what w0lf said:
private const string requireNonPrintableChar = "\x0005";
But if you want your second paramter for cound, use:
private static readonly string requireNonPrintableChar = new string('\x0005', 1); // should be greater than 1

"cannot be resolved to a variable" compile error

I'm trying to get my code to check whether or not a certain string is in the enumerated type. This is what I have:
public enum CurrencyAmt {twenty(20), ten(10), five(5), toonies(2), toony(2), loonies(1), loony(1), quarters(0.25),
quarter(0.25), dimes(0.1), dime(0.1), nickels(0.05), nickel(0.05), pennies(0.01), penny(0.01);
private int type;
private double value;
CurrencyAmt (int i)
{
this.type = i;
}
CurrencyAmt (double i)
{
this.value = i;
}
}
defines my enum type. And the expression
(Enum.IsDefined(typeof(CurrencyAmt), inputAt)
to check if the string 'inputAt' is in the enum. However, i receive the error CurrencyAmt cannot be resolved to a variable. Any ideas?
You need a .class after CurrencyAmt, I reckon:
(Enum.IsDefined(typeof(CurrencyAmt.class), inputAt)
However, as I don't recognise any other parts of this code snippet from Java, I think the Java version should be:
CurrencyAmt.valueOf(inputAt);
...which will return the CurrencyAmt enum constant that corresponds to the given string or will throw an exception if it's not defined.

Use int constant in attribute

Can anybody explain why I can't use a const Int32 in an C# attribute?
Example:
private const Int32 testValue = 123;
[Description("Test: " + testValue)]
public string Test { get; set; }
Makes the compiler say:
"An attribute argument must be a constant expression, ..."
Why?
As the error states, an attribute argument must be a constant expression.
Concatenating a string and an integer is not a constant expression.
Thus, if you pass "Test: " + 123 directly, it will give the same error.
On the other hand, if you change testValue to a string, it will compile.
Explanation
The rules for constant expressions state that a constant expression can contain arithmetic operators, provided that both operands are themselves constant expressions.
Therefore, "A" + "B" is still constant.
However, "A" + 1 uses the string operator +(string x, object y);, in which the integer operand is boxed to an object.
The constant-expression rules explicitly state that
Other conversions including boxing, unboxing and implicit reference conversions of non-null values are not permitted in constant expressions.
'+' operator between int and string causes invocation of ToString method of int which is not "Compile time constant". It is like this
private const int x = 3;
private const string s = x.ToString(); // cannot be done
You can only pass compile time evaluated constants including result of typeof() operators and excluding decimals into Attributes constructors

order initializiation static parameter

Is there any specification for the order in which static readonly parameters are initialized?
In the following example, can one be sure, the array is always created with a length of 6?
public class Foo {
private static readonly int MAX_STACKSIZE = 6;
private static readonly int[] m_stack = new int[MAX_STACKSIZE];
}
Or is there any chance of m_stack being initialized before MAX_STACKSIZE ?
#Edit: changed const to static readonly
EDIT: This answer was written when the sample code contained "const" instead of "static readonly". It's not valid for the current version of the question - I may write another answer to deal with that at some point, but I don't have time right now.
That won't be valid C# anyway, as you can't set a const int[] to anything other than null.
However, in the more general case, section 10.4 of the C# spec applies:
Constants are permitted to depend on other constants within the same program as long as the dependencies are not of a circular nature. The compiler automatically arranges to evaluate the constant declarations in the appropriate order.
It then gives the following example:
class A
{
public const int X = B.Z + 1;
public const int Y = 10;
}
class B
{
public const int Z = A.Y + 1;
}
and says...
the compiler first evaluates A.Y, then evaluates B.Z, and finally evaluates A.X, producing the values 10, 11 and 12 in that order.

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