Why declare a local function static in C# 8.0 - c#

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.

Related

Is A Class Member Variable Bound Or Free (In Terms Of Combinators)?

While I realize I'm not being very rigorous, I'm pretty sure the definition of a combinator in simple terms is simply a function with no free variables. For example,
f(x,y) = x + y
would be a combinator and
f(x,y) = x * 2
would not be because y would be free.
So given that understanding would a member variable in a class definition be considered "free"? I'm guessing it would but I wanted to check my assumption. Code like this C# example:
namespace ConsoleApplication1
{
class BoundOrFree
{
private int _i = 0;
public int f(int x, int y)
{
return x + y + _i;
}
}
}
In the BoundOrFree.f member function is _i free? Would f therefore not be a combinator? I'm assuming the answer to both of those questions would be yes but I wanted to confirm my assumption.
would not be because y would be free
you misinterpret the "free" term in this case. Free variable is the one that was captured from the outer scope (via a closure). So f(x,y) = x * 2 is a combinator.
Answering your question
In the BoundOrFree.f member function is _i free? Would f therefore not be a combinator?
the BoundOrFree::f function is not a combinator, since it uses variables other than its only arguments.

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;

Uncover the mystery of how lambda works [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Detailed Explanation of Variable Capture in Closures
public class Polynom {
public delegate double Func(double x);
private Func f;
public Polynom(params double[] coef) {
f = (double x) => {
double sum = 0;
for ( int i = 0 ; i < coef.Length ; i++ )
sum += coef[i] * Math.Pow(x,coef.Length-1-i);
return sum;
};
}
public double evaluate(double x) {
return f(x);
}
public static void Main() {
Polynom a=new Polynom(1,1,1);
Polynom b=new Polynom(2 , 2 , 0);
Console.WriteLine(a.evaluate(2));
Console.WriteLine(b.evaluate(2));
Console.ReadKey();
}
}
Notice how the code in f uses coef, while coef is a paramater of the constructor.
if you think about it, that should not work unless it gets a ref copy of coef, because once the constructor done its job, its parameters are suppose to vanish. but somehow, calling f manages to use coef as if it still exists. HOW?
I would love a good deep explantion if someone can explain this...
Another thing that i would like to know is, the code is the same on every Polynom instance, but does every instance get another copy of that same code? if so, is there a way to make my class run with just 1 copy of that code? (like make it static somehow)
Lambdas and other delegates are implemented as closures, special objects created by the compiler that combine a method of your lambda with all the data that the lambda needs to complete its execution. The values of all local variables and parameters that are used inside the lambda are implicitly captured as data members of the closure, so they remain available until the lambda itself is no longer referenced.
You can think of the closure as a special anonymous class created specifically for your lambda. In your case, a closure may look like this:
private Polynom_Closure {
private readonly double[] coef;
public Polynom_Closure(double[] coef) {
this.coef = coef;
}
public double evaluate(double x) {
double sum = 0;
for ( int i = 0 ; i < coef.Length ; i++ )
sum += coef[i] * Math.Pow(x,coef.Length-1-i);
return sum;
}
}
The compiler makes this class invisibly for you, and then inserts its use into your code:
public Polynom(params double[] coef) {
f = new Polynom_Closure(coef).evaluate;
}
The function is a so-called closure, which is well-explained in this wikipedia article
A closure allows a function to access variables outside its immediate lexical scope. An upvalue is a free variable that has been bound (closed over) with a closure. The closure is said to "close over" its upvalues. The referencing environment binds the nonlocal names to the corresponding variables in scope at the time the closure is created, additionally extending their lifetime to at least as long as the lifetime of the closure itself. When the closure is entered at a later time, possibly from a different scope, the function is executed with its non-local variables referring to the ones captured by the closure.
Concerning your second question: Making a closure static would somewhat contradict the purpose of functional principles.

How to avoid initialization of these variable?

I was reading on the net (http://www.codinghorror.com/blog/2005/07/for-best-results-dont-initialize-variables.html) that we should not initialize variables.
Somehow I dont get it. Often I just cannot avoid that. Lets look on a simple example:
public int test(string s)
{
int start = 0;
int mod = 2;
int output = 0;
foreach (int i in s)
{
output = output + (i % mod) + start;
start++;
}
return output;
}
Ok its maybe a nonsense :-) But the question is: can I avoid the initialization? Maybe its not possible for mod, because mod have to be 2 from the beginning and it will stay 2. But how about start and output? I just cannot write int start because thats always Error Use of unassigned local variable. Maybe int start = null would be better, but in this case its not gonna work too. So how to avoid this stuff?
You've misread his article. In his article he is specifically talking about initialization of variables with respect to classes. In the case you've put forth, your variables should be initialized before they can be used because they'll be immediately used.
Edit: Yes, in this specific case the int variables don't need initialization because the compiler automatically initializes an int to 0, but if this is taken to a different degree with a string or a DateTime, initialization becomes important in the context of a method.
You misread the article. The article is talking about member variables (which are automatically initialized to default values and therefore do not require explicit initialization), but you are trying to apply the rule to local variables (which are not automatically initialized and therefore require explicit initialization).
You can rewrite you method like this
public int Test(string s) {
const int mod = 2;
int start;
int output = 0;
foreach(int i in s) {
output = output + (i % mod) + start;
start++;
}
return output;
}
In this case, the start variable does not need to be initialised, and that is true whether declare in inner or outer scope.
However, the output variable does need initialisation due to the fact that it will be returned by the method, and is possible that if the loop never runs, the variable would never be initialised.
The article is talking about not to initialize variables with default values. For example,
int x = 0;
is not good. Also, you should initialize (and declare) the variable just before it's usage is a clean code.
Initialization in constructor is not just before the usage.

Can I use a reference inside a C# function like C++?

In C++ I can do this:
int flag=0,int1=0,int2=1;
int &iRef = (flag==0?int1:int2);
iRef +=1;
with the effect that int1 gets incremented.
I have to modify some older c# code and it would be really helpful if I could do something similar, but I'm thinking ... maybe not. Anybody?
UPDATE: The feature discussed below was finally added in C# 7.
The feature you want - to make managed local variable aliases is not supported in C#. You can do it with formal parameters - you can make a formal parameter that is an alias of any variable - but you cannot make a local which is an alias of any variable.
However, there is no technical difficulty stopping us from doing so; the CLR type system supports "ref local variables". (It also supports ref return types but does not support ref fields.)
A few years back I actually wrote a prototype version of C# which supported ref locals and ref return types, and it worked very nicely, so we have empirical evidence that we can do so successfully. However, it is highly unlikely that this feature will be added to C# any time soon, if ever. See http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/ for details.
I note that if I were you, I would avoid this in any language. Writing programs in which two variables share the same storage makes for code that is hard to read, hard to understand, hard to modify and hard to maintain.
See also the related question: Why doesn't C# support the return of references?
You can do it - or at least something very similar to what you want - but it's probably best to find another approach. For example, you can wrap the integers inside a simple reference type.
If you still want to do it, see the Ref<T> class posted by Eric Lippert here:
sealed class Ref<T>
{
private readonly Func<T> getter;
private readonly Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value { get { return getter(); } set { setter(value); } }
}
public class Program
{
public static void Main()
{
int flag=0,int1=0,int2=1;
Ref<int> iRef = (flag == 0 ?
new Ref<int>(() => int1, z => { int1 = z; }) :
new Ref<int>(() => int2, z => { int2 = z; }));
iRef.Value += 1;
Console.WriteLine(int1);
}
}
Output:
1
If all you need is to modify a value type within a function, then pass the parameter with the ref keyword.
int i = 0;
void increment(ref int integer)
{
integer++;
}
increment(ref i);
Yes you can do that with C# 7.0. It has support for returning references and storing references. See my answer here.
Fraid not. You could do it with unsafe code and pointers like so:
int flag=0,int1=0,int2=1;
unsafe
{
int *iRef = (flag==0? &int1:&int2);
*iRef +=1;
}
(not saying that's a good idea or anything :))
There is no direct equivelent in C#. There are a couple of options -
You can use unsafe code and pointers as suggested by dkackman.
Another alternative is to use a reference type (class) which holds the value. For exmaple:
// Using something like
public class Wrapped<T> {
public Wrapped(T initial) {
this.Value = initial;
}
public T Value { get; set; }
}
// You can do:
bool flag=false;
var int1 = new Wrapped<int>(0);
var int2 = new Wrapped<int>(1);
Wrapped<int> iRef = flag ? int2 : int1;
iRef.Value = iRef.Value + 1;
Since you're working with references to a class, the assignment to iRef copies the reference, and the above works...
You could use an Action delegate like this:
int flag = 0, int1 = 0, int2 = 0;
Action increment = flag == 0 ? (Action) (() => ++int1) : () => ++int2;
increment();

Categories

Resources