Retain local variable across method calls - c#

Is there a way in C# to have a method retain a variable across different calls? For example:
private void foo()
{
int j; //declare this so as it isn't destroyed with the stack frame.
int i = calculateSomeValue() + j;
j = i;
}
The normal way I would do this would be with a member variable like this:
private int j = 0;
private void foo()
{
int i = calculateSomeValue() + j;
j = i;
}
I don't like how the variable j can be accessed in all of the other methods of the class. Plus it just seems messy this way: defining a member variable when it will only be used in one method to keep track of the value of i when the method was last called.
Is this possible in a nice/clean way? Or should I just use the member variable way and forget about it?

You could use a tiny little nested class to encapsulate it, along these lines:
public class Test
{
private int foo()
{
return nested.foo();
}
private int calculateSomeValue()
{
return 42;
}
readonly Nested nested = new Nested();
private class Nested
{
private int j;
public int foo()
{
int i = calculateSomeValue() + j;
j = i;
}
}
}
The methods in the outer class will only be able to access the public members of Nested, so they can only access foo() in this example - j is inaccessible. But note that methods in Nested have access to all the private members of the outer class.

I don't think there is another way of giving the scope you ask. The fact that other methods can access j in this case being a member variable is a direct consequence of the OOP concepts your are using encapsulating the members inside the holder object.
So I would continue using the member variable and don't worry about other methods being able to access it. If for some reason you must avoid other methods accessing the variable, maybe you should consider refactoring in its own type although maybe with the example given is not justified.
Hope this helps.

There is a nasty way to do that using closures. But that means you have to define your methods as anonymous functions and have them wrapped in some global method where they are defined. Consider this more an academical exercise and definitely not a production solution. For a real life solution definitely consider a separate class.
static void Main(string[] args)
{
var j = 0;
Func<int> calculateSomeValue = () =>
{
return 41;
};
Action myFoo = () =>
{
int i = calculateSomeValue() + j;
j = i;
};
}

In C this is possible with static local variables
void foo()
{
static int j;
int i = calculateSomeValue() + j;
j = i;
}
In C# this functionality was intentionally not included.
You have a couple of options, which depends on the intended lifetime of j. If you just need it for successive calls and for some reason don't want to use a loop, you can go for a recursive approach
private void foo()
{
foo(0);
}
private void foo(int j)
{
int i = calculateSomeValue() + j;
foo(j);
}
If you want more control or a longer lifetime, the objected oriented way would be to push this functionality onto a class, which can be a normal class or private and nested in your existing class.
public class ParentClass()
{
FooClass bar = new FooClass();
private class FooClass()
{
private int j = 0;
public void foo()
{
int i = calculateSomeValue() + j;
j = i;
}
private int calculateSomeValue()
{
//
}
}
private void DoStuff()
{
bar.foo();
}
}
Also I suggest re-weighing if its worth it to protect the variable in the first place.

Related

Reference in functions C#

I know from the title you would say it's a duplicate, but...
So, I have created my class and made some objects (of class Masina) in MainWindow class constructor:
public class MainWindow
{ // example
private Masina[] _masina = new Masina[10];
_masina[0].Load(1, 'x'); // works
SomeFunction(_masina);
}
When I use this class functions in Constructor it works fine, but when I try to use some function and pass this argue like this:
public static void SomeFunction(Masina[] masina)
{
for (int i = 0; i < 10; i++)
try
{
masina[i].Load(i, 'x');
}
catch
{
}
}
then SomeFunction takes this argue as not referenced. ref don't work for me!
Can anyone help me to solve ?
Probably you want to initialize the Masina[] array in the constructor, like this:
public class MainWindow {
// Declaraion is OK, calling method _masina[0].Load(1, 'x') - is not
private Masina[] _masina = new Masina[10];
// constructor is the place you're supposed to put complex initialization to
public MainWindow() {
// You can call the method in the constructor
SomeFunction(_masina);
}
public static void SomeFunction(Masina[] masina) {
// validate arguments in the public methods
if (null == masina)
throw new ArgumentNullException("masina");
// do not use magic numbers (10), but actual parameters (masina.Length)
for (int i = 0; i < masina.Length; ++i)
masina[i].Load(i, 'x');
// hiding all exceptions - catch {} - is very bad idea
}
}

Automatic properties

I want to know that when you create an Automatic property
and invoke the set in the main() method for a random value , where is that value being stored ?as in this example :
class Program
{
static void Main(string[] args)
{
Example W = new Example();
W.Num = 10;
Console.WriteLine("{0}", W.Num);
Console.WriteLine("{0}", W.getNum());
}
}
class Example
{
private int num;
public int Num { get; set; }
public int getNum() { return num; }
}
why is the output :
100
Because you are returning num, not Num. And num was not initialized, so this value is 0.
Auto-implemented properties makes code cleaner when no additional logic is required for the getter or setter. The compiler actually generates a backing field for the auto-implemented property, but this backing field is not visible from your code.
In your example there is no connection between the num field and the Num property, so there no reason why the num should change.
This is nothing abnormal here.
When you call
Example W = new Example();
then initially num = 0 and Num = 0;
you assigned Num, not num.
num in your Example class is redundant.
If you wrote this before automatic property initialisers were added to c#, it would look like this:
private int num;
public int Num
{
get{ return num;}
set{ num = value;}
}
Writing public public int Num { get; set; } is essentially the same thing behind the scenes. There is no need to implement getNum() (like Java), since this is equivalent to int a = w.Num;.
if use new keyword , you created new instance your class And all object recreated.
For Example ;
class Program
{
static void Main(string[] args)
{
Example W = new Example();
W.Num = 10;
Example W1 = new Example();
Console.WriteLine("{0}", W.Num); //10
Console.WriteLine("{0}", W1.Num); //0
}
}
this is only information your answer ; you returning different variable. you not set them.

How to instantiate unique delegates using an anonymous method in a loop (in C#)?

Code:
using System.IO;
using System;
using System.Reflection;
using System.Collections.Generic;
class AnyClass
{
delegate void Del(string str);
static void Main()
{
List<Del> listDel = new List<Del>();
listDel.Add(delegate(string str) { });
Console.WriteLine( listDel[0].Method.ToString() );
listDel.Add(delegate(string str) { });
Console.WriteLine( listDel[1].Method.ToString() );
for (int i = 0; i < 2; i++)
{
listDel.Add(delegate(string str) { });
}
Console.WriteLine( listDel[2].Method.ToString() );
Console.WriteLine( listDel[3].Method.ToString() );
}
}
Output:
Void m__0(System.String)
Void m__1(System.String)
Void m__2(System.String)
Void m__2(System.String)
Why do the delegates instantiated in the loop "point" to the same method (m__2) whereas the ones instantiated outside the loop point to two different methods (m__0 and m__1)?
Is there any way how to instantiate delegates that point to different/unique methods inside a loop?
Example of usage: I need to have delegates as keys in a dictionary, so they need to be unique. Instantiation inside a loop is necessary to provide enough of flexibility.
Why do the delegates instantiated in the loop "point" to the same
method (m__2) whereas the ones instantiated outside the loop point to
two different methods (m__0 and m__1)?
Because behind the scenes the compiler is caching the delegate creation. When you create the first two delegates, the compiler doesn't have knowledge that they are the same, so he creates two different cached delegates and two named methods. Inside your for loop, the compiler is optimizing by only instantiating the delegate once. He can be certain that it's the same delegate each time, instantiate it once, then cache it.
When you de-compile your code, it actually looks like this:
private delegate void Del(string str);
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate3;
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate4;
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate5;
private static void Main()
{
List<Launcher.Del> listDel = new List<Launcher.Del>();
List<Launcher.Del> arg_24_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate3 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate3 =
new Launcher.Del(Launcher.<Main>b__0);
}
arg_24_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate3);
Console.WriteLine(listDel[0].Method.ToString());
List<Launcher.Del> arg_5D_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate4 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate4 =
new Launcher.Del(Launcher.<Main>b__1);
}
arg_5D_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate4);
Console.WriteLine(listDel[1].Method.ToString());
for (int i = 0; i < 2; i++)
{
List<Launcher.Del> arg_9A_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate5 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate5 =
new Launcher.Del(Launcher.<Main>b__2);
}
arg_9A_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate5);
Console.WriteLine(listDel[2 + i].Method.ToString());
}
}
[CompilerGenerated]
private static void <Main>b__0(string str)
{
}
[CompilerGenerated]
private static void <Main>b__1(string str)
{
}
[CompilerGenerated]
private static void <Main>b__2(string str)
{
}
I would definitely not rely on a delegate being a proper key for a Dictionary.
Is there any way how to instantiate delegates that point to
different/unique methods inside a loop?
You can force the delegate to be a "fresh instance" only by explicitly creating a new Del instance yourself and passing a new named method each time. There are other more "fishy" ways of doing so, but I wouldn't recommend taking those paths just to get a new delegate.
Is there any way how to instantiate delegates that point to different/unique methods inside a loop?
You can't make each loop iteration create a different method because methods are hard-coded into the assembly. Their number is fixed while the loop could be unbounded.
You can make each syntactic appearance of a lambda have a different method by using some kind of hack:
Action<int> x = i => {
if (Environment.CurrentManagedThreadId < 0 /*always false*/)
Console.WriteLine(i + uniqueIntegerHere);
};
This forces each method body to be unique and the compiler cannot ever optimize this away. You can of course pull the body into a helper method.
If you want unique delegates per loop iteration you either need to create methods at runtime or keep a set of statically compiled methods:
void F1() { }
void F2() { }
void F3() { }
...
T4 templates come to mind.
Yet another way similar to the one proposed by #usr. You can force compiler to create a new instance of delegate object using reflection method Delegate.CreateDelegate(type, this, methodInfo). The trick goes at the point where this parameter is always a new object thus forcing myMethod being called on it and thus each delegate actually represents a different context for compiler.
This requires the method for delegation to be inside a separate class, which you can instantiate. I am not sure this requirement fits you actual task. Perhaps you will be inspired for another solution based on this one...
using System.IO;
using System;
using System.Reflection;
using System.Collections.Generic;
class AnyClass
{
delegate void Del(string str);
private static Dictionary<Del, string> dict = new Dictionary<Del, string>();
static void Main()
{
List<Del> listDel = new List<Del>();
int count = 10;
for (int i = 0; i < count; i++)
{
listDel.Add(factory());
dict.Add(listDel[i ], "Delegate " + (i));
}
for (int i = 0; i < count; i++)
{
Console.WriteLine(listDel[i].Method.ToString());
listDel[i].Invoke((i).ToString());
}
Console.ReadLine();
}
public class DelegateEncapsulator
{
private int _number;
public DelegateEncapsulator(int number)
{
_number = number;
}
public void myMethod(string str) {
Console.WriteLine("Delegate " + _number + " " + str);
}
}
private static int delegateCounter = 100;
private static Del factory()
{
var obj = new DelegateEncapsulator(delegateCounter++);
var ret = (Del)Delegate.CreateDelegate(typeof(Del), obj,
typeof(DelegateEncapsulator).GetMethod("myMethod"));
return ret;
}
}
This code adds all delegates into a dictionary. You can play with number elements to be added.
Hope this helps

How can fix System.StackOverflow Exception?

I used 2 classes, and I need send/receive methods and variables. But when I make an instance of this class it gives me a System.StackOverflowException.
How can fix this problem?
This is my code:
class Setup1
{
Setup2 set2 = new Setup();
int a = 5;
public int myMethod();
{
set2.b = a + 10;
return set2.b;
}
}
class Setup2
{
Setup1 set1 = new Setup();
public int b = 0;
void Show()
{
MessageBox.Show(set1.myMethod());
}
}
You have an infinite recursion.
In the constructor of Setup2() you call the constructor of Setup1(). There you call the constructor of Setup2()and so on, infinitely. Your memory runs out, and your stack overflows.
It seems that you have cyclic constructor calling that leads to stack-overflow exception.

How to Avoid Assignment of Private Members in Constructor

I often find myself doing this:
class MyClass
{
public MyClass(int x)
{
this.x = x;
}
private int x;
...
}
Every time I add a new private member variable for configuration, I need to add it to the constructor's parameter list, to the constructor body, and to the class as a member. Is there a good programming pattern for avoiding the extra typing?
Generally speaking, If you instantiate a class with a bunch of private members that you have to pass into the constructor, you're doing something problematic already.
MyClass myClass = new MyClass(x, y, z, 7, 'c', someOtherClass)
If appropriate, you can encapsulate related fields into a struct or a different class like so
class MyClass
{
public MyClass(Coordinates coords)
{
this.coords = coords;
}
private Coordinates coords;
}
public struct Coordinates
{
public int X{get; set;}
public int Y{get; set;}
public int z{get; set;}
}
and then you can instanciate it with
MyClass myClass = new MyClass(new Coordinates() { X = 1, Y = 2, Z = 3 });
Without a particular implementation, It's kinda hard to determine the optimal solution, but if you don't actually have to set the fields from outside your class, you can do something like
class MyClass
{
public MyClass()
{
}
private int x = 2;
...
}
or
class MyClass
{
public MyClass()
{
this.x = 2;
}
private int x;
...
}
I find that I can abuse inheritance to accomplish my goal. I set up a "Loader" subclass that has the sole purpose in life of plugging in the dependencies of the base class. Then we can work with the base class and forget about the loader.
Then again, this has the horrible side-effect of preventing use of these protected member variables in the base constructor -- we need to use a .Start() function or something like that instead. So, this is a pretty bad solution, although saving some keystrokes.
public class MyClass
{
protected int param1;
protected int param2;
public void DoStuff()
{
Console.WriteLine(param1 + param2);
}
}
public class MyClassLoader : MyClass
{
public MyClassLoader()
{
param1 = 1;
param2 = 2;
}
}
class Program
{
static void Main(string[] args)
{
MyClass myObj = new MyClassLoader();
myObj.DoStuff();
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
}
}

Categories

Resources