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...
Related
Consider the following code:
private unsafe void Function()
{
int length;
// This line raises error CS1686, "Local 'length' or its members cannot have their address taken and be used inside an anonymous method or lambda expression".
glGetProgramiv(1, GL_PROGRAM_BINARY_LENGTH, &length);
FunctionWithLambda(() => Console.WriteLine(length));
}
private void FunctionWithLambda(Action callback)
{
callback();
}
Note that I'm taking the address of length (a local variable), then using the variable itself (not its address) in a lambda. I understand why a local variable address can't be used in a lambda directly (see Why cannot I pass the address of a variable to an anonymous function?, among other examples), but why can't I use the value of length once assigned (even if that assignment happens to use the & operator)? The official documentation for error CS1686 (https://learn.microsoft.com/bs-latn-ba/dotnet/csharp/misc/cs1686) hasn't clarified this confusion.
My assumption is that this is simply a language limitation, but I'm curious if there's an underlying technical reason I'm missing. Also note I'm not asking how to work around this problem (I know I can easily copy length to another local variable first).
The C# specification says the following (my bold):
23.4 Fixed and moveable variables
The address-of operator (§23.6.5) and the fixed statement (§23.7) divide variables into two categories:
Fixed variables and moveable variables.
...snip...
The & operator (§23.6.5) permits the address of a fixed variable to be obtained without restrictions. However, because a moveable variable is subject to relocation or disposal by the garbage collector, the address of a moveable variable can only be obtained using a fixed statement (§23.7), and that address remains valid only for the duration of that fixed statement.
In precise terms, a fixed variable is one of the following:
A variable resulting from a simple-name (§12.7.3) that refers to a local variable, value parameter, or parameter array, unless the variable is captured by an anonymous function (§12.16.6.2).
.....
So it's explicitly forbidden by the spec. As to why it's forbidden, for that you would have to ask the language designers, but considering how much complexity is involved in capturing variables, it is somewhat logical.
I guess the reason is simple: Too complex to compile.
There are 2 problems the compiler has to solve:
Generate a clourse for the anonymous method.
Synchronize the value of the variable.
Let's assume the following codes are valid.
unsafe void Function()
{
int length = 1;
void bar() => Console.WriteLine(length);
bar();
foo(&length);
bar();
}
unsafe void foo(int* i) { (*i)++; }
Expected result is:
1
2
To solve the first problem C# will generate an anonymous class to hold the upvalue.
Here is the pseudocode:
class _Anonymous
{
public int _length;
public void _bar() { Console.WriteLine(_length); }
}
unsafe void Function()
{
int length = 1;
var a = new _Anonymous { _length = length };
a._bar();
foo(&length);
a._bar();
}
To solve the second problem C# uses the generated field instead of the original local variable.
unsafe void Function()
{
//int length = 1;
var a = new _Anonymous { _length = 1 };
a._bar();
foo(&a._length);
a._bar();
}
These are all the works that a compiler can do. But till now the codes still won't work, we need an extra fixed block.
unsafe void Function()
{
var a = new _Anonymous { _length = 1 };
a._bar();
fixed (int* p = &a._length)
foo(p);
a._bar();
}
So the limitation can be removed with a smarter compiler, but things get more easy if we forbid such kind of codes.
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.
I have the following code, that I use as sample for illustrating different scenarios:
public static void MethodWithOptionalGuid(Guid id = default(Guid)) { }
public static void MethodWithOptionalInteger(int id = 2) { }
public static void MethodWithOptionalString(string id = "33344aaa") { }
public static void MethodWithoutOptionalParameter(int id, Guid longId) { }
static void Main(string[] args)
{
var methods = typeof(Program).GetMethods(BindingFlags.Public | BindingFlags.Static).ToList();
foreach (var method in methods)
{
PrintMethodDetails(method);
}
Console.ReadLine();
}
static void PrintMethodDetails(MethodInfo method)
{
Console.WriteLine(method.Name);
foreach (var parameter in method.GetParameters().ToList())
{
Console.WriteLine(parameter.Name +
" of type " + parameter.ParameterType.ToString() +
" with default value:" + parameter.DefaultValue);
}
Console.WriteLine();
}
It prints the following:
MethodWithOptionalGuid
id of type System.Guid with default value:
MethodWithOptionalInteger
id of type System.Int32 with default value:2
MethodWithOptionalString
id of type System.String with default value:33344aaa
MethodWithoutOptionalParameter
id of type System.Int32 with default value:
longId of type System.Guid with default value:
The output seems fine for the last 3 methods.
My question is regarding the first one, MethodWithOptionalGuid: why the Guid's default value is not recognized?
I expected to receive something like "0000000-..." . I also tried initializing the optional parameter with new Guid() and same result. I tried as well other structs, like TimeSpan and the behavior is the same.
I expected that all value types would behave the same (as seen in integer example).
Extra: I found this thing while trying to use in Asp.Net MVC an action with an optional Guid parameter and failed (had to make the Guid nullable). Went through MVC code and found that it uses the DefaultValue at some point. So I made this code sample to better illustrate my issue.
The why is pretty relevant and something you really need to heed when you want to do something like this. Dragons live here. If you use ildasm.exe to look at the method then you'll see:
.param [1] = nullref
A null as a default for a structure type, uh-oh. The semantics for the .param directive is described in the CLI spec, Ecma-335, chapter II.15.4.1.4. It is very short, I'll copy-paste the entire chapter (edited for readability)
MethodBodyItem ::= .param ‘[’ Int32 ‘]’ [ ‘=’ FieldInit ]
This directive stores in the metadata a constant value associated with method parameter number Int32,
see §II.22.9. While the CLI requires that a value be supplied for the parameter, some tools can use the
presence of this attribute to indicate that the tool rather than the user is intended to supply the value of
the parameter. Unlike CIL instructions, .param uses index 0 to specify the return value of the method,
index 1 to specify the first parameter of the method, index 2 to specify the second parameter of the
method, and so on.
[Note: The CLI attaches no semantic whatsoever to these values—it is entirely up to compilers to
implement any semantic they wish (e.g., so-called default argument values). end note]
The [Note] is most relevant. When you use Reflection then you play the role of the compiler and it is up to you to interpret the default value correctly. In other words, you have to know that in C# the default value for a structure type is null.
This is otherwise a limitation in what can be stored in a [FieldInit]. The initialization value must be stored in the metadata of the assembly and is subject to the same kind of limitations of an [attribute] declaration. Just simple value types can be used, not structures. So by convention the C# designers worked around this by using null instead. Good enough for the C# compiler to understand that default(Guid) was intended.
That's not where the trouble ends, there are other ways to indicate an optional argument, the [OptionalAttribute] was used prior to C# v4.0. And is still used today, by COM interop libraries and other languages like VB.NET and C++/CLI. That's where the dragons live.
Ignoring those beasts for now, workaround code for what you have could look like this:
var def = parameter.DefaultValue;
if (parameter.ParameterType.IsValueType && def == null) {
def = Activator.CreateInstance(parameter.ParameterType);
}
Console.WriteLine(parameter.Name +
" of type " + parameter.ParameterType.ToString() +
" with default value:" + def);
Open your testfile with a decompiler of your choice and you will see that your code actually get compiled to:
public static void MethodWithOptionalGuid(Guid id = null) { }
This is why the DefaultValue property returns null.
When you use this parameter now, lets say you add:
Console.WriteLine(id);
The compiler will insert a
box [mscorlib]System.Guid
statement before the WriteLine. Now the output will be the expected "0000000-..."
Sorry - I can't tell you WHY it doesn't return the correct value but I've a workarround using this extension method:
public static object GetDefaultValue(this ParameterInfo p)
{
if (!p.Attributes.HasFlag(ParameterAttributes.HasDefault))
{
return null;
}
if (p.DefaultValue != null || p.RawDefaultValue != null)
{
return p.DefaultValue ?? p.RawDefaultValue;
}
return p.ParameterType.IsValueType ? Activator.CreateInstance(p.ParameterType) : null;
}
Maybe it will help.
I guess the answer can be found in c# language specifications (someone may find something more relevant)
Point 4.1.2
When the operands of an expression are all simple type constants, it
is possible for the compiler to evaluate the expression at
compile-time. Such an expression is known as a constant-expression
(§7.19). Expressions involving operators defined by other struct types
are not considered to be constant expressions.
Through const declarations it is possible to declare constants of the
simple types (§10.4). It is not possible to have constants of other
struct types, but a similar effect is provided by static readonly
fields.
Even if we're not talking about expressions or consts here, it seems that only simple types (structs like int) can be evaluated /computed at compile time. That's why default(int) can be evaluated and then would display 0 in your code.
But other struct can't be computed at compile time, so I would say that it's the reason why they're evaluated to null.
When you set a default parameter value, it has to be a compile-time constant.
The tricky part is that you can put default(Guid) or new Guid() as an accepted compile-time constant (BUT evaluated to null), but... it can't be a const.
For example, you could not do
const Guid g = new Guid();
I am building internal logic for a game in C# and coming from C++ this is something that might be lost in translation for me.
I have an object, Ability that calculates the bonus it provides and returns that as an integer value. The calculation is meant to be dynamic and can change depending on a variety of variables.
public class Ability: Buffable
{
public string abbr { get; private set; }
public Ability(string name, string abbr, uint score) : base(name, score)
{
this.abbr = abbr;
}
// Ability Modifier
// returns the ability modifier for the class.
public int Ability_modifier()
{
const double ARBITARY_MINUS_TEN = -10;
const double HALVE = 2;
double value = (double)this.Evaluate();
double result = (value + ARBITARY_MINUS_TEN) / HALVE;
// Round down in case of odd negative modifier
if (result < 0 && ((value % 2) != 0))
{
result--;
}
return (int)result;
}
I then have another object, Skill which should be aware of that bonus and add it into it's calculation. I wanted to pass an Ability into the constructor of Skill by reference and then store that reference so that if the Ability changed the calculation would as well. The obvious problem with this being that apparently storing references is taboo in C#.
Is there either a work around way to do this or an alternate way to approach this problem that my pointer infested mind isn't considering? I would greatly prefer not to have to pass the ability to the function that evaluates Skill every time, since the one referenced never changes after construction.
The obvious problem with this being that apparently storing references is taboo in C#.
Absolutely not. References are stored all over the place. You're doing it here, for example:
this.abbr = abbr;
System.String is a class, and therefore a reference type. And so the value of abbr is a reference.
I strongly suspect you've misunderstood how reference types work in C#. If you remember a reference to an object, then changes to the object will be visible via the reference. However, changes to the original expression you copied won't be.
For example, using StringBuilder as a handy mutable reference type:
StringBuilder x = new StringBuilder("abc");
// Copy the reference...
StringBuilder y = x;
// This changes data within the object that x's value refers to
x.Append("def");
// This changes the value of x to refer to a different StringBuilder
x = new StringBuilder("ghi");
Console.WriteLine(y); // abcdef
See my articles on references and values, and parameter passing in C# for much more detail.
I am not quite seing enough of your code to give a concrete example, but the way to do this is to pass in a lambda delegate such as () => object.property instead of this: object.property.
In C#, there are reference types and value types. All non-value-type objects are passed by reference, so there should be no issue with references. Just pass it, and it will be passed by reference.
class app {
public int x = 3;
static void Main(string[] args)
{
}
}
it's possible get the memory address allocated by x variable?
the example can be in C, C++, C# or D.
I hope it is clear
Thanks in advance
The ampersand (&) is the "address-of" operator in most C-like languages:
int x;
printf("Address of x is %p\n", &x);
The return value of & is effectively a pointer to its operand.
In C and in C++ this is fairly straight-forward. I'll give the example in C++:
struct App
{
int x;
App() : x(3) { }
};
int main()
{
App a;
int * p = &a.x; // address goes here
}
There is of course no such thing as "the variable App::x", since App is only the type. Each instance of this type, such as a in the example, carries its own set of member variables, and a pointer to the member variable is readily obtained. (The same is true for plain data structs in C.)
Note that C++ has another, related feature: Member pointers. This allows us to form the opaque value int App::*pm = &App::x which by itself doesn't point to anything, but only carries information about the offset of App::x inside the class, if you will. This animal can be used together with an instance to obtain the actual value, e.g. a.*pm.
Skipping D and E. C# and F# (and other CLR languages) - there is no fixed addres for any partcular variable in general. One can use managed debugger (i.e. WinDbg + SOS) to find address of any particular variable, or use fixed along with interop classes.