C# global variables unchangeable outside of locality? - c#

Variables declared and initialized in Main, are not able to be changed through methods belonging to
other classes. This is extremely unintuitive and there must be a way around this.
Anyone know why, and how to solve? Or am I not understanding something fundamental about inheritance.
TestClass stuff = new TestClass();
int test = 1;
Console.WriteLine("This is an integer: {0}\nAnd this is an amount it's added with: 2", test);
stuff.ChangeVariable(test);
Console.WriteLine("\nand it's {0} here! Why doesn't the change stick!?", test);
class TestClass
{
public void ChangeVariable(int item)
{
item += 2;your text
Console.WriteLine("\nFor some reason, 'item' here is {0},", item);
}
}

You are not understanding something fundamental.
Your code doesn't use inheritance. Your code has two classes but they don't inherit. You are using an implicit Main method that belongs to a class and you are defining a class named TestClass. These two classes have no relation to each other.
There are no global variables in C#. int test is a local variable in the implicit Main method.
int is a value type, not a reference type. When you pass test to the ChangeVariable() method, the value of test is passed but not a reference to the test variable. The changes made to item are limited to the ChangeVariable() method.

If you don't use the ref keyword, it won't change the variable in the other class.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
So if you want it to change the variable, your code should look like this:
using System;
TestClass stuff = new TestClass();
int test = 1;
Console.WriteLine("This is an integer: {0}\nAnd this is an amount it's added with: 2", test);
stuff.ChangeVariable(ref test);
Console.WriteLine("\nand it's {0} here! Why doesn't the change stick!?", test);
class TestClass
{
public void ChangeVariable(ref int item)
{
item += 2;
Console.WriteLine("\nFor some reason, 'item' here is {0},", item);
}
}

Related

Difference between Action and delegate instantiation and accessibility

Why is MyDeler "static", as in I can access MyDeler through the class name, but I can't explicity say public "static" delegate void MyDeler(), nor can I access d through an instance of MyClass, as in new MyClass.d()?
Further, why is it that I have to new up a MyClass to use MyVoidAction?
See code below:
using System;
public class MyClass
{
public delegate void MyDeler();
public Action MyVoidAction;
}
class MainClass
{
static void Main()
{
MyClass.MyDeler d = () => Console.WriteLine("my deler");
d();
// MyClass.MyVoidAction mva1 = () => Console.WriteLine("my void action"); // not allowed, why?
MyClass meClass = new MyClass();
meClass.MyVoidAction = () => Console.WriteLine("my void action");
meClass.MyVoidAction();
}
}
I looked up this answer: Accessibility between Action and Delegate
That cleared up a lot, but I'm not sure I'm 100% on this. So according to that answer, the delegate void MyDeler() defines a type, which confuses me because I imagine something like this:
using System;
class MainClass
{
class MyClass
{
public static class DelegateClass
{
public void DoDel() // isn't even legal?
{
Console.WriteLine("DoDel()");
}
}
}
static void Main()
{
//MyClass.DelegateClass d = new asdf // ??? something like this?
}
}
Help appreciated!
Let's demystify this:
When you declare MyDeler:
public delegate void MyDeler();
What you are doing is defining a type of method to which execution will be "delegated". In other words, you are saying there is method out there that follows this signature and I intend to keep references to it. In order for the compiler to identify these references, this type will be used.
It follows then that you will need to actually have a real pointer to the method, since this is just your "definition". That's why you will need a variable of type "MyDeler" to which you can assign the actual method to call:
MyClass.MyDeler d = () => Console.WriteLine("my deler");
This line is saying "create a variable named d of type MyClass.MyDeler that holds a reference to this inline method". From here on, when you call d(); the pointer will actually execute the inline method.
For the action:
public Action MyVoidAction;
You are now declaring a public property of the class. Therefore, you need an instance of the class before you can use this property.
The trick here is that Action is a known definition of a delegate. Microsoft has a built-in type that you can use instead of declaring your own void MyDeler();. It's essentially syntactical sugar but remember, it's still a type and as you have created a public property, you now need to assign it the method that will actually execute and as we discussed before, you need an instance:
MyClass meClass = new MyClass(); //Instance creation
meClass.MyVoidAction = () => Console.WriteLine("my void action"); //Tell your delegate what to delegate to.
meClass.MyVoidAction(); //Run the inline method!
I hope that helps.
MyDeler is a type declaration, not a variable declaration. You can't store things in it or assign to it.
To create a field for storing a MyDeler instance, add this line to MyClass:
public MyDeler MyDelerField;
Now you can assign to it.
Why is MyDeler "static", as in I can access MyDeler through the class name, but I can't explicity say public "static" delegate void MyDeler(), nor can I access d through an instance of MyClass, as in new MyClass.d()?
The declaration of MyDeler declares a type within MyClass. It's similar to declaring any other nested type, like:
class MyClass
{
public class MyNestedClass { }
}
It is a member of the type MyClass, not of any actual instance of MyClass, nor even of the class MyClass as a static member would be.
A nested type is neither "instance" nor "static", because it's part of the type system, not part of the class itself.
why is it that I have to new up a MyClass to use MyVoidAction?
Because MyVoidAction is a member of the class, and is an instance member. So you are required to have an instance of the class to access it.
the delegate void MyDeler() defines a type, which confuses me because I imagine something like this
Your declaration in that example of public static class DelegateClass is doing something completely different. An unfortunate aspect of C# is the use of static to refer to a variety of different things. It's not quite as bad as in Java, but it can still be confusing (as you're finding out).
In that declaration, the use of the word static does not make DelegateClass a "static member" of the containing type MyClass. Instead, the word static as part of a class declaration means that the entire class will contain only static members.
Thus, when you declare DoDel() without the static keyword, you are attempting to declare an instance member, i.e. that method, in a class where you've promised to declare only static members. If you add static to the method declaration, it would compile.
Not that doing so would make the DelegateClass class in that example similar to the MyVoidAction member in your other example. It's still a type declaration, declaring a nested type within the MyClass class, and would still follow the rules for types, not class members. But I hope that at least explains to you why the example that's confusing you works the way it does.
Action and a delegate of a method with no parameters and that returns void are formally the same thing.
If u take a look to: https://msdn.microsoft.com/en-us/library/system.action(v=vs.110).aspx you can see that:
You can use this delegate to pass a method as a parameter without
explicitly declaring a custom delegate.
I hope this example helps:
public delegate void DelegateMyDeler(); //This is a custom delegate
public class MyClass
{
public DelegateMyDeler MyDeler; //This use your custom delegate
public Action MyVoidAction; // This use Action delegate
}
class MainClass
{
static void Main()
{
// MyClass.MyDeler d = () => Console.WriteLine("my deler"); // Now this is not allowed too!
// d();
// MyClass.MyVoidAction mva1 = () => Console.WriteLine("my void action"); // not allowed, why?
MyClass meClass = new MyClass();
meClass.MyDeler = () => Console.WriteLine("my deler");
meClass.MyDeler();
meClass.MyVoidAction = () => Console.WriteLine("my void action");
meClass.MyVoidAction();
//but you can do (you custom delegate is defined out of the class in this case
//so you have not to add the class prefix):
DelegateMyDeler d = () => Console.WriteLine("my deler 2");
d();
// or
DelegateMyDeler d3 = () => Console.WriteLine("my deler 3");
d3.Invoke();
// and in a real case, for example:
DelegateMyDeler undeterminedMethod;
int x = 3;
switch (x)
{
case 1:
undeterminedMethod = deler1;
break;
case 2:
undeterminedMethod = deler2;
break;
case 3:
undeterminedMethod = deler3;
break;
default:
undeterminedMethod = null;
break;
}
undeterminedMethod?.Invoke(); //In case x is minor than 1 or major than 3, nothing happens
}
static void deler1() { Console.WriteLine("my deler 1"); }
static void deler2() { Console.WriteLine("my deler 2"); }
static void deler3() { Console.WriteLine("my deler 3"); }
}

Extension methods, which is a better choice

Following is a test class
public class Test
{
public int a;
}
Following are the Extension methods I have created:
public static class Extension
{
public static void Do1(this Test t,int value)
{
t.a = t.a + value;
}
public static Test Do2(this Test t,int value)
{
t.a = t.a + value;
return t
}
}
Code Usage:
Test t = new Test();
t.a = 5;
Both the following calls lead to same result for t.a, which is 10:
t.Do1(5)
t = t.Do2(5)
There are many instances in my code where I need to implement a similar logic, which one is better, one of them is passing reference by value and internally updating it, other is returning the updated reference. Is using one of them safer, if this kind of code ever gets into multi threaded wrapper, provided all the thread safety is taken care of. Normally to update the referenced variable we need a ref or out keyword, which is like pointer to a pointer, instead of a separate pointer to same memory location as in this case, but here in extension methods, I cannot use them. Please let me know if the question needs further clarity
In your example it does not make sense to return the tvariable. t is a reference, so setting t.a updates the object already. There's no need for ref, out or returning t. One reason for returning t would be to allow you to use method chaining.
You only need ref or out if you want to actually change the reference, not the content of the reference.
You are actually misunderstanding sense of ref and out keywords. Those are used, if you want to replace whole referenced object inside your method, for simple property level update they are not needed at all.
In your example, as Test is a class (reference type), there is no actual difference between two methods, but returning initial Test object as in Do2 method is just pointless, as object was already updated. So best of two will be the first implementation:
public static class Extension
{
public static void Do1(this Test t,int value)
{
t.a = t.a + value;
}
}
Going back to Do2 method - as I said before, referenced object value is already updated inside a method, so there is even no point in assigning return value to initial variable:
t.Do2(5)
is the same as
t.Do(5)

Why does a lambda expression preserve enclosing scope variable values after method terminates?

I was under the impression that lambda expression contexts in C# contain references to the variables of the parent function scope that are used in them. Consider:
public class Test
{
private static System.Action<int> del;
public static void test(){
int i = 100500;
del = a => System.Console.WriteLine("param = {0}, i = {1}", a, i);
del(1);
i = 10;
del(1);
}
public static void Main()
{
test();
}
}
outputs
param = 1, i = 100500
param = 1, i = 10
However, if this was true, the following would be illegal, because the lambda context would reference a local variable that went out of scope:
public class Test
{
private static System.Action<int> del;
public static void test(){
int i = 100500;
del = a => System.Console.WriteLine("param = {0}, i = {1}", a, i);
}
public static void Main()
{
test();
del(1);
}
}
However, this compiles, runs and outputs
param = 1, i = 100500
Which means that either something weird is going on, or the context keeps values of the local variables, not references to them. But if this was true, it would have to update them on every lambda invokation, and I don't see how that would work when the original variables go out of scope. Also, it seems that this could incur an overhead when dealing with large value types.
I know that, for example, in C++, this is UB (confirmed in answer to this question).
The question is, is this well-defined behaviour in C#? (I think C# does have some UB, or at least some IB, right?)
If it is well-defined, how and why does this actually work? (implementation logic would be interesting)
The concept of closures as they relate to the lambda syntax in C# is a very large topic and too large for me to cover everything in just this answer but let's try to answer the specific question here at least. The actual answer is at the bottom, the rest between is background needed to understand the answer.
What happens when the compiler tries to compile a method using anonymous methods is that it rewrites the method to some extent.
Basically, a new class is generated and the anonymous method is lifted into this class. It's given a name, albeit an internal one, so for the compiler it sort of transitions from an anonymous method into a named method. You, however, doesn't have to know or handle that name.
Any variables that this method required, variables that was declared besides the anonymous method, but in the same method that used/declared the anonymous method, will be lifted as well, and then all usages of those variables is rewritten.
There's a couple of methods involved here now so it becomes hard to read the above text so instead let's do an example:
public Func<int, int> Test1()
{
int a = 42;
return value => a + value;
}
This method is rewritten to something like this:
public Func<int, int> Test1()
{
var dummy = new <>c__DisplayClass1();
dummy.a = 42;
return dummy.<Test1>b__0;
}
internal class <>c__DisplayClass1
{
public int a;
public int <Test1>b__0(int value)
{
return a + value;
}
}
The compiler can handle all these funky names (and yes, they really are named with all the brackets like that) because it refers to things with id's and object references, the names are no longer an issue for the compiler. You, however, can never declare a class or a method with those names so there's no risk of the compiler generating a class that just happens to already exist.
Here's a LINQPad example that shows that a class I declared, although with less brackets in its names, looks identical to the one generated by the compiler:
void Main()
{
var f1 = Test1();
f1(10).Dump();
f1.Dump();
var f2 = Test2();
f2(10).Dump();
f2.Dump();
}
public Func<int, int> Test1()
{
int a = 42;
return value => a + value;
}
public Func<int, int> Test2()
{
var dummy = new __c__DisplayClass1();
dummy.a = 42;
return dummy._Test2_b__0;
}
public class __c__DisplayClass1
{
public int a;
public int _Test2_b__0(int value)
{
return a + value;
}
}
output:
If you look at the screenshot above you notice two things for each delegate variable, a Method property, and a Target property.
When calling the method, it is called with a this reference referring to the Target object. A delegate thus captures two things: Which method to call, and the object on which to call it.
So basically, that object of that generated class survives as part of the delegate because it is the target of the method.
With all that in mind, let's look at your question:
Why does a lambda expression preserve enclosing scope variable values after method terminates?
A: If the lambda survives, all the captured variables survive as well because they're no longer local variables of the method they were declared in. Instead they were lifted onto a new object that also has the lambda method, and thus "follows" the lambda everywhere it goes.

Field initializer accessing `this`: invalid in C#, valid in Java? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
First, an introduction:
This code:
class C
{
int i = 5;
byte[] s = new byte[i];
}
fails to compile with the following error:
A field initializer cannot reference the nonstatic field, method, or property `C.i'
Resharper says something similar: Cannot access non-static field i in static context.
This is inline with what the C# spec says -- that a field initializer can't access the instance currently being created (this) or, by extension, any of the instance fields:
A variable initializer for an instance field cannot reference the
instance being created. Thus, it is a compile-time error to reference
this in a variable initializer, as it is a compile-time error for a
variable initializer to reference any instance member through a
simple-name.
However, this works just fine in Java:
class C {
int i = 5;
byte s[] = new byte[i]; //no errors here
}
Still with me? Ok, here's the question. Err, questions.
In a hypothetical world where this would be valid in C#, I'm wondering: would it even be possible? If so, what would be the pros and cons that it would add to the table?
Also, since it's really supported by Java, do the same pros/cons hold for Java? Or is there a fundamental difference in the way type initializers work in the two languages?
In short, the ability to access the receiver before the constructor body runs is a feature of marginal benefits that makes it easier to write buggy programs. The C# language designers therefore disabled it entirely. If you need to use the receiver then put that logic in the constructor body.
as for why the feature is legal in Java, you'll have to ask a Java designer.
In C#, field initializers are merely convenience semantics for the developer. The compiler moves all field initializers into the body of the constructor ABOVE where the call is made to the base constructor. So fields are initialized going up the ancestor chain, and the class is initialized from the base down.
Static references are ok because they are initialized before anything else.
By no means is this an authoritative answer, but let me make an educated guess.
There is a fundamental difference, and I think the answers to the other questions are related to this difference.
It lies in order-of-type-initialization, especially in the context of inheritance.
So, how does instance initialization work?
In C#:
all instance field initializers run first, "up" the inheritance chain, from most derived to base class.
then the ctors run, "down" the chain, from base to derived.
The possibility of ctors calling each-other or (explicitely) calling ctors of base classes doesn't change the situation, so I'll leave it out.
What basically happens is, this runs for each chass in the chain, starting with the most derived:
Derived.initialize(){
derivedInstance.field1 = field1Initializer();
[...]
Base.Initialize();
Derived.Ctor();
}
A simple example shows this:
void Main()
{
new C();
}
class C: B {
public int c = GetInt("C.c");
public C(){
WriteLine("C.ctor");
}
}
class B {
public int b = GetInt("B.b");
public static int GetInt(string _var){
WriteLine(_var);
return 6;
}
public B(){
WriteLine("B.ctor");
}
public static void WriteLine(string s){
Console.WriteLine(s);
}
}
Output:
C.c
B.b
B.ctor
C.ctor
That means that if accessing fields in a field initializer was valid, I could do this disaster:
class C: B {
int c = b; //b is a field inherited from the base class, and NOT YET INITIALIZED!
[...]
}
In Java:
Long, interesting article about type initialization here. To summarize:
It's a bit more complicated, because besides the notion of instance field initializers, there's the notion of an (optional) instance initializer, but here's the gist of it:
Everything runs down the inheritance chain.
the instance initializer of the base class runs
the field initializers of the base class run
the ctor(s) of the base class run
repeat above steps for the next class down the inheritance chain.
repeat previous step until reaching the most derived class.
Here's the proof: (or run it yourself online)
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
new C();
}
}
class C extends B {
{
WriteLine("init C");
}
int c = GetInt("C.c");
public C(){
WriteLine("C.ctor");
}
}
class B {
{
WriteLine("init B");
}
int b = GetInt("B.b");
public static int GetInt(String _var){
WriteLine(_var);
return 6;
}
public B(){
WriteLine("B.ctor");
}
public static void WriteLine(String s){
System.out.println(s);
}
}
Output:
init B
B.b
B.ctor
init C
C.c
C.ctor
What this means is, by the time a field initializer runs, all inherited fields are already initialized (by initializer OR ctor in base class), so it's safe enough to allow this behaviour:
class C: B {
int c = b; //b is inherited from the base class, and it's already initialized!
[...]
}
In Java, like in C#, the field initializers are run in the order of declaration.
The Java compiler even goes through the effort of checking that the field initializers aren't called out-of-order* :
class C {
int a = b; //compiler error: illegal forward reference
int b = 5;
}
* As an aside, you can access fields out-of-order if the initializer calls an instance method to do so:
class C {
public int a = useB(); //after initializer completes, a == 0
int b = 5;
int useB(){
return b; //use b regardless if it was initialized or not.
}
}
It is because field initialisers are moved into the constructor by the compiler (unless static) and so you would need be explicit in your constructor like this:
class C
{
int i = 5;
byte[] s;
public C()
{
s = new byte[i];
}
}
This is a bit of a non-answer, but I like to think of anything in the body of a class as being sequence-independent. It's not supposed to be sequential code that needs to be evaluated in a particular manner--it's just default state for the class. If you use code like that, you're expecting i to be evaluated before s.
Anyways, you can just make i a const (as it should be), anyways.

C# Variable Scope stopping me in my tracks

I'm fairly new to programming. The the constant issue I keep facing when I try anything for myself in C based languages is the scope.
Is there any way to use or modify a variable from within a different method or class? Is there also a way to do this without creating a new intance of a class or object? It seems to wipe the slate clean every time.
Example, I'm setting up a console text game, and I want a different background message to write to the console at certain intervals.
public static void OnTimedEvent(object scource, ElapsedEventArgs e)
{
if(Exposition.Narration == 1)
{
Console.WriteLine("The bar is hot and muggy");
}
if (Exposition.Narration == 2)
{
Console.WriteLine("You see someone stealing beer from the counter");
}
if (Exposition.Narration == 3)
{
Console.WriteLine("There is a strange smell here");
}
}
But I have no way of making different messages play. If I create the variable from within the method it will send that variable to its defult everytime it runs. If I create a new instance of an object or a class, it sends things back to the defult as well. Also, I can't modify a single class when I'm creating new instances of them all the time.
That's just one example of where its been a problem. Is there a way to have a varable with a broader scope? Or am I thinking about this the wrong way?
edit:
To put it simply can I read or change a variable from within a different method or class?
using System;
namespace Examp
{
class Program
{
public static void Main(string[] args)
{
int number = 2;
other();
}
public static void other()
{
if (Main.number == 2)
{
number = 3
}
}
}
}
While I don't think I understood completely your question, you can see here some ways to make a variable "persist" outside a method:
Static variables
Static variables are something like a global variable. You can see them through all the program if you set them as public (if you set them as internal, it's different).
A static variable can be defined as:
class MyClass
{
static int MyVariable = 4;
}
....somewhere...
void MyMethod()
{
MyClass.MyVariable = 234;
}
As you can see, you can access them anywhere.
Variables on heap
If you create an object with new operator, if you keep reference to that object, every modify you do on it, it reflects on all references to that object that you have. For example
class MyClass
{
int X;
}
static class Program
{
static void Main(string args[])
{
MyClass a = new MyClass();
a.X = 40;
Method1(a);
Method2(a);
Console.WriteLine(a.X.ToString()); // This will print 32
}
static void Method1(MyClass c)
{
c.X = 10;
}
static void Method2(MyClass c)
{
c.X = 32;
}
}
You can even use refs to edit your variables inside a method
Basically you misunderstood the concept of "scope", because you question is "which variable types exist" (global/static/local etc.). What you would like to know about scope is this: A local variable exists only within { } where it's defined.
I hope this gives you some suggestion. The answer is definitely not complete but can give you an idea.
Try to be more specific so I can change my answer.
Answer to edit 1:
No you can't change a variable in the way you want, you must add it to the class (Program in this case), try adding:
class Program
{
static int number;
....
}
Obviusly you should remove the one inside the Main method.
Also note that int can't be modified (except without a ref) inside a function if you pass them as parameters because they are copied.
The reason is quite simple: a reference to a Class instance is (at least) the same size as an int (if we are speaking about 32/64 bit systems), so it takes the same time copying it or referencing it.
You can return a value from a method after you have done your calculations if you want, like this:
int x = 3;
x = DoSomethingWithX(x);
int DoSomethingWithX(int x)
{
x += 30;
}
Class access modifiers allow you to control the members that you want the class to expose to other classes. Furthermore, static class with singleton pattern allow use to reuse the same instance across your application.
Looking at your example, it appears that you are simply trying to read the class member, hence a public property in your class should suffice. The instance of this class can be passed while initializing the class in which your OnTimedEvent method is present (this method should be changed to an instance method to access non static members of the your class).
For example,
class MyClass
{
private Exposition exposition;
// Option 1: Use parametrized constructor
// Pass the instance reference of the other class while
// constructing the object
public MyClass(Exposition exposition)
{
this.exposition = exposition;
}
// Option 2: Use an initialize method
public void Initialize(Exposition exposition)
{
this.exposition = exposition;
}
// Remove static to access instance members
public void OnTimedEvent(object scource, ElapsedEventArgs e)
{
// Better to use an enumeration/switch instead of magic constants
switch(exposition.Narration)
{
case HotAndMuggy:
Console.WriteLine("The bar is hot and muggy");;
break;
...
}
}
// Option 3: Use static properties of the Exposition class
// Note this approach should be used only if your application demands
// only one instance of the class to be created
public static void OnTimedEvent_Static(object scource, ElapsedEventArgs e)
{
// Better to use an enumeration/switch instead of magic constants
switch(Exposition.Narration)
{
case HotAndMuggy:
Console.WriteLine("The bar is hot and muggy");;
break;
...
}
}
}

Categories

Resources