order initializiation static parameter - c#

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.

Related

Why declare a local function static in C# 8.0

In C# 8.0, Static Local Functions are announced
Can anyone help enlighten me as to why you would want to declare a local function as static?
The reason given in in the article:
to ensure that local function doesn't capture (reference) any variables from the enclosing scope
But:
I don't understand why would you want to ensure that?
Is there any other reason or benefits to declare it static? (performance maybe?)
The example code given in the article is:
int M()
{
int y = 5;
int x = 7;
return Add(x, y);
static int Add(int left, int right) => left + right;
}
I don't understand why would you want to ensure that?
Because it prevents you from shooting yourself in the foot. It forces the local function to be a pure function that does not modify the state of the caller.
This returns false, because the function modifies local variables of its caller:
public bool Is42()
{
int i = 42;
Foo();
return i == 42;
void Foo()
{
i = 21;
}
}
And this doesn't, because it doesn't even compile:
public bool Is42()
{
int i = 42;
Foo();
return i == 42;
static void Foo()
{
i = 21;
}
}
It prevents surprises. Of course in these simple examples the benefit isn't immediately clear, because "well it's obvious that Foo() modifies i", but in larger codebases maintained by multiple people and not properly covered by unit tests, this simple modifier prevents grief.
Capturing variables has a small additional cost as it will generate an internally used type where your captured variables are public fields. Consider a slightly modified example:
int M()
{
int y = 5;
int x = 7;
return Add();
int Add() => x + y;
}
It will actually translate to something like this:
int M()
{
int y = 5;
int x = 7;
var capturedVars = new <>c__DisplayClass0_0 { x = x, y = y };
return <M>g__Add|0_0(ref capturedVars);
}
[CompilerGenerated]
private struct <>c__DisplayClass0_0
{
public int x;
public int y;
}
[CompilerGenerated]
internal static int <M>g__Add|0_0(ref <>c__DisplayClass0_0 class_Ref1) =>
(class_Ref1.x + class_Ref1.y);
This answer from CodeCaster and this separate answer from György Kőszeg individually answer different parts of my question, so I'm bringing them both together to form the full picture for the accepted answer:
For Part 1) of my question, #CodeCaster Says:
Because it prevents you from shooting yourself in the foot. It forces the local function to be a pure function that does not modify the state of the caller.
in larger codebases maintained by multiple people and not properly covered by unit tests, this simple modifier prevents grief
So Answer 1 is: Static Local Functions ensure reliable caller method state.
For Part 2) of my question, #György Kőszeg Says:
Capturing variables has a small additional cost as it will generate an internally used type where your captured variables are public fields
And he goes on to give an example of the produced compiler code via reflector.
So Answer 2 is: Static Local Functions prevent variable capturing. Variable capturing comes at a small cost. So there is a small performance boost by declaring the local function static
I think this is just to ensure correct usage of the variables used in the local function, as the documentation says. In large and complex methods, it can prevent accidental usage of enclosing scope variables if there are variables with the same name in the local function.

TryParse create inline parameter?

Is there any way in C# to create a variable inline?
Something like this:
int x = int.TryParse("5", out new int intOutParameter) ? intOutParameter : 0;
Don´t you think that this is more useful than creating a variable outside and then never use it again?
That syntax – called declaration expressions – was on the proposed feature list for the next version of C# (version 6).
You're not the only one to think it is useful. For instance making a complete TryParse call an expression (no need for a statement to declare the variable).
However it has been dropped from the ongoing work to C#6.
I'm sure I'm not the only one hoping it will make a return in a future version.It is included in C#7 as a declaration (no need for new):
int x = int.TryParse("5", out int intOutParameter) ? intOutParameter : 0;
Inline declarations for out params is a new suggested feature in C# that might be standard one day, see e.g. Probable C# 6.0 features illustrated, section 9. The expected/proposed syntax:
int.TryParse("5", out int x); // this declares (and assigns) a new variable x
Edit: This out variable syntax was eventually included in C# 7.0 (Visual Studio 2017); you can also use out var x.
Addition: People come up with fun extension methods. I tried to make a generic one:
public delegate bool TryParser<TResult>(string s, out TResult result);
public static class FunExtensions
{
public static T TryParse<T>(this string str, TryParser<T> tryParser)
{
T outResult;
tryParser(str, out outResult);
return outResult;
}
}
This can be used like this:
var x = "5".TryParse<int>(int.TryParse);
var y = "01/01".TryParse<DateTime>(DateTime.TryParse);
var z = "bad".TryParse<decimal>(decimal.TryParse);
and so on. I was hoping the compiler would infer T from usage, so that one could say simply:
var x = "5".TryParse(int.TryParse); // won't compile
but it appears you have to explicitly specify the type argument to the method.
As a workaround you could create an extension:
public static int TryParse(this string input, int defaultValue = default(int))
{
int intOutParameter;
bool parsable = int.TryParse(input, out intOutParameter);
if (parsable)
return intOutParameter;
else
return defaultValue;
}
Then you don't even need an out-parameter:
int parsed = "5".TryParse(0);
Based on OP request:
private static bool IsIntValid(string str)
{
int i = 0;
return int.TryParse(str, out i);
}
Granted not the most cleverest approach however, the simplest I guess :) Can wrap this in an extension method also perhaps.
You can also use a temporary storage for all methods.
public static class Tmp<T>
{
[ThreadStatic]
public static T Value;
}
 
int x = int.TryParse("5", out Tmp<int>.Value) ? Tmp<int>.Value : 0;

How to use scientific notation in const fields?

I'm working in a math library, and due to the inherent troubles of working with double I am coding all equality comparisons type a == b as Math.Abs(a - b) <= epsilon.
Also, by default, I want my formatted strings to be generated with the maximum considered precision. That is, if epsilon is 0.001 I want my default format to be N3.
Happily I did the following:
public static class Math3D
{
internal const int ROUND = 3;
public const double Epsilon = 1e-ROUND;
}
...and I got a compilation error. Apparently this is not allowed.
With this limitation I see no way I can define both interdependant constants as consts. Obviously I can define Epsilon as a readonly field but I feel doing so is somehow conceptually wrong. Am I missing an obvious way of how to do this?
If you're going to possibly be changing it, you should use readonly here. const should really be used for things that will never change, like π. The reason for this is because of a subtle difference between const and readonly.
The main issue is that if you change the value of the const, you must recompile all dependent clients that use the const, otherwise you can shoot yourself in the foot, badly. So for values that might change, don't use const, use readonly.
So, if the value is never going to change, just use const and then don't worry about defining Epsilon in terms of ROUND, just say:
internal const int ROUND = 3;
public const double Epsilon = 1e-3;
If you really want to make sure you don't accidentally change one without changing the other, you could add a small check in the constructor:
if (Epsilon != Math.Pow(10, -ROUND)) {
throw new YouForgotToChangeBothConstVariablesException();
}
You could even add conditional compilation so that only gets compiled in debug releases.
If it is going to change, use static readonly:
internal readonly int ROUND = 3;
public static readonly double Epsilon = Math.Pow(10, -ROUND);
With this limitation I see no way I can define both interdependant constants as consts. [...] Am I missing an obvious way of how to do this?
No, you need to do some kind of math using Math.Pow or Math.Log to go between ROUND and Epsilon and those are not acceptable for compile-time usage with const. You could write a miniature code generator to spit out these two lines of code based on a single input value, but I really question the value of investing time into that.
1e-ROUND, specifically 1e is not a valid literal integer. You would have to do something like,
public static readonly double Epsilon =
decimal.Parse(
string.Format("1E-{0}", ROUND),
System.Globalization.NumberStyles.Float);
Also, note the static readonly since you cannot use a const when the expression won't be known until runtime. The static readonly will work similarly to a const in this scenario.
If you prefer not dealing with strings, you can always do,
public static readonly double Epsilon = Math.Pow(10, -ROUND);
You could always just hard code the 3. Seeing as you are using constants, then have no intention of ever changing the value to anything other than 3 right? So you don't need to worry too much about DRY.
public static class Math3D
{
internal const int ROUND = 3;
public const double Epsilon = 1e-3;
}
If you are thinking you might want to change the 3, then const is not for you and your question becomes moot.
Edit:
This is not a direct answer to your question but have you considered changing Round and Epsilon into writable fields? If you use these for formatting / rounding, it's almost guaranteed they'll need to change on occasion - neither a const nor a readonly field will work for that.
public static class Math3D
{
internal static int s_Round;
internal static double s_Epsilon;
static Math3D ()
{
Round = 3;
}
public static double Epsilon
{
get
{
return ( s_Epsilon );
}
}
public static int Round
{
get
{
return ( s_Round );
}
set
{
// TODO validate
s_Round = value;
s_Epsilon = Math.Pow ( 10, -s_Round );
}
}
}
It's a clearly readable solution that won't break when you change things in the future.

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.

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