Static as a local variable inside function in C# [duplicate] - c#

This question already has answers here:
Why doesn't C# support local static variables like C does? [closed]
(13 answers)
Closed 3 years ago.
I came to know that,
From MSDN:
C# does not support static local variables (variables that are declared in method scope).
And here:
The static modifier can be used with classes, fields, methods, properties, operators, events, and constructors, but it cannot be used with indexers, destructors, or types other than classes.
That is, local variables are not allowed as static inside a method.
Therefore, the below code will not compile
public class Base1
{
public int getHighscoreString()
{
int highscore = Int32.MinValue;
static int max = 10; // It is not allowed here.
if(max>highscore)
highscore = max;
return highscore;
}
}
But, we can always do the same functionality by
public class Base1
{
static int max = 10;
public int getHighscoreString()
{
int highscore = Int32.MinValue;
if(max>highscore)
highscore = max;
return highscore;
}
}
So, is it a design decision that static variable can not be used as local variable inside a method or any reason behind it?

A static variable is a variable that lives beyond the instances of the class in which is declared, in the sense that to get or set its value you have to call its class type and not its instances. This happens because a reference to the memory address where the static variable lives is kept regardless of the construction or disposal of instances of that class. Say you have a Zoo class:
public class Zoo
{
public static int counter;
public string Name;
public void AddAnimal(string name)
{
Name = name;
counter++;
}
}
The counter increases every time you add an animal to the zoo, and you can get the total anytime by calling
Zoo myZoo = new Zoo()
myZoo.AddAnimal(“tiger”);
Zoo.counter; // 1
myZoo.counter // wrong!
Apart from myZoo.counter being wrong, the main thing to notice is that even if we dispose of the myZoo instance, the counter field will always keep the total of the animals in the zoo!
On the contrary, variables declared in a method are immediately disposed after method execution and therefore you cannot reference them outside of that method because the memory address where the variable “lived” is not available anymore.
I hope this clarifies the matter a little more. Cheers!

Related

How does the constructor set the default value of a class' members?

According to this link, Constructors enable the programmer to set default values, limit instantiation, and write code that is flexible and easy to read.
class Program
{
static void Main(string[] args)
{
var a = new MyClass();
Console.WriteLine($"i: {a.i}, b: {a.b}"); //result --> i: 0, b: False
}
}
public class MyClass
{
public int i;
public bool b;
public MyClass() { }
}
My constructor doesn't have a single line of code. At what point the members of my class get initialized? And what if I don't provide a default constructor but rather a constructor that take some parameters? The documentation doesn't explain that assertion. Do codes similar to this get injected?
public class MyClass
{
public int i;
public bool b;
public MyClass()
{
i = default;
b = default;
}
}
Thanks for helping
ECMA-334 specification, which defines the C# standard, says this:
10.4.2 - Initially assigned variables
The following categories of variables are classified as initially assigned:
Static variables.
Instance variables of class instances.
Instance variables of initially assigned struct variables.
Array elements.
Value parameters.
Reference parameters.
Variables declared in a catch clause or a foreach statement.
So the compiler ensures that these variables are always set to default. This is easily backed up by the CLR, which always initializes all such variable locations (note that local variables are specifically not in the above list).
ECMA-335, which defines the CLR, says:
I.8.11.2 - Field definitions
snip
Fields not marked as static define the representation of a value of a type by defining the substructure of the value (see §I.8.4.1). Locations for such fields are created within every value of the type whenever a new value is constructed. They are initialized during construction of the new value.
When you define a class it is present virtually like blueprint of any design. So When you move to its implementation it becomes reality. Same goes for object and classes in any Object oriented language. When you define class, you basically define blueprint it does not exist yet but when you create object of class, it is created in memory. So in your first case where you have constructor without any arguments when you create object memory space is reserved based on its member and types.
public class MyClass
{
public int i;
public bool b;
public MyClass() { }
}
In this case when you create object, memory is reserved for int and bool. it does not matter whether you have parameterized constructor where you are assigning values to class members or not. Memory space is reserved with default values for int and bool in heap.

"this" is unavailable when directly initializing class member variable [duplicate]

This question already has answers here:
Cannot use 'this' in member initializer?
(3 answers)
Closed 7 years ago.
Why does the compiler give an error about this being unavailable that when initializing an instance variable when defining it?
Keyword 'this' is not available in the current context
The constructor initialization is fine. I understand the scenario here - I just wanted to find the reason (via MSDN or otherwise) why "this" is available to a constructor but not directly if initializing the member variable.
Here is a simple abstraction of the error I'm seeing.
public class ClassA
{
// Gets compiler error that "this" unavailable
protected ClassB _a1 = new ClassB(this);
// Works fine
protected ClassB _a2;
public ClassA() { _a2 = new ClassB(this); }
}
public class ClassB
{
public ClassA A { get; private set; }
public ClassB(ClassA a) { this.A = a; }
}
I was hoping to keep my initialization next to the assignment since the above example is an abstraction of my code where I am defining Lazy valueFactory delegates for 10-15 member variables in which the delegates need the data context passed as a parameter to the constructor. With 15 member variables, I'd prefer to keep the assignment next to the definition on a single line instead of having 15 lines of definitions and then another 15 lines in the constructor initializing each one.
This is basically what I had to do in my actual code:
public class MyContext
{
public ProgramService Programs { get { return _programs.Value; } }
protected Lazy<ProgramService> _programs;
public MyContext()
{
_programs = new Lazy<ProgramService>(() => new ProgramService(this));
}
}
Basically to keep you from relying on the order (textual) and possibly non-usable state of the class under construction. I think the overriding principle at stake is that if it's "complicated" logic, then you should be using a constructor.
Eg., doing this:
class A {
private int x = 1;
private int y = this.x + 1;
}
would lead to different results than:
class A {
private int y = this.x + 1;
private int x = 1;
}
which is a little unexpected. To side-step the issue, but still allow the convenience of inline init - disallowing this makes the ordering not matter.
In your actual code, you could possibly do a lazy check to keep things located together:
public ProgramService Programs {
get {
if (_programs == null) _programs = new ProgramService(this);
return _programs.Value;
}
}
// change this to private to keep subclasses from accessing a possibly null reference
private Lazy<ProgramService> _programs;

Public variable inside a class

I am a bit confused about how public variables work inside a class.
I know that public variables can be accessed without calling the class, whereas private ones cannot.
If you have multiple instances of the same class and in each you give a different value to a public variable then i assume each class instance would have its own unique version of the variable each with a different value.
My confusion is this
What happens if you change the value of the public variable without calling a new instance of the class?
Would all future new instances of the class start with that variable set to whatever you set it to without first calling the class? if not then what happens?
I think you somehow mixed up public variables and static variables. The below statement:
public variables can be accessed without calling the class
Is utterly and plainly wrong for non static variables, might they be private or public.
If you change public variable of a class instance, it will change only that instance, having no effect whatsoever on other existing instances or future instances.
Static variables on the other hand can indeed be called without an instance of the class and changing them has "global" effect, not related to class instance.
(If you have any specific code you worked with and need further guidance please post it)
In languages like C#, you can´t do that.
Accessing any (non-static) variable of a class itself instead of a instance of it
would result in a compiler error.
Perhaps some sample code will help; private variables cannot be accessed so I'm guessing your terminology is getting mixed up. In the below sample, the PublicStaticInt property is declared as static; simply put, that means there is only one copy of it in your AppDomain. Every instance of ExampleClass that is created references that same copy of it. The PublicInt property is an instance property; that means that every instance of ExampleClass has its own copy of that piece of data.
public class ExampleClass
{
public static int PublicStaticInt { get; set; }
public int PublicInt { get; set; }
}
private static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
var example = new ExampleClass();
Console.WriteLine("PublicStaticInt = " + ExampleClass.PublicStaticInt.ToString() + ", PublicInt = " + example.PublicInt);
ExampleClass.PublicStaticInt++;
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
When you create a new instance of same class then every instance has its own values for each data members. for example
class A
{
public int a;
public int b;
public A()
{
a=0;
b=0;
}
}
when i create instance of class A like this
A a11 =new A();
A b11 = new A();
Now if I change the value of a11 it will never change the value of b11 and if I change the value of b11 it will never change the value of a11.
Would all future new instances of the class start with that variable set to whatever you set it to without first calling the class? if not then what happens?
No they will set to values that you have set in the constructor of the class. In this case it will set values of a and b equal to zero for every instance of class because it is done the constructor.

How variable stored in class and their flow of execution?

I am new to C# programming.
Please help me.
I created a class Tester:
class Tester
{
public int a = 5;
public int b = a;
}
Question 1 : Why am I not able to use this variable a for initializing the variable b.
Question 2: If I changed the variables to static then it works fine. Why is there a difference?
class Tester
{
public static int a = 5;
public static int b = a;
}
Question 3 : In previous example if I swap the sequence of variable then it works fine why because a is declaring after b . How can it initialize a?
class Tester
{
public static int b = a; // 0
public static int a = 5; // 5
}
There are some icky initialization order issues when you use fields initializers. A simple example would be:
class Test {
int a = b;
int b;
public Test() {
b = 1;
}
}
What will be the value of a? If you use the constructor-initializes-object rule then a will be 1. That however not the way it works under the hood, a would be 0 if the syntax where valid. A side-effect of the way field initializers are implemented, their code is injected into the constructor before the code in the body of the constructor. This problem gets a lot more convoluted when the class inherits base classes that have constructors.
This is too ugly, the C# language designers solved this by simply forbidding this kind of code. The rule is that you cannot reference this in a field initializer, that will create a reference to an object whose class constructor hasn't finished executing.
The rule is relaxed for static fields, there is no this reference and the CLR provides decent guarantees for class initializer execution order. That however doesn't avoid ambiguity, it is an exercise to guess what the field values will be in this example:
class Test {
static int a = b + 1;
static int b = a + 1;
}
Try it and see if you can make sense of the result. It is otherwise well-defined.
Answer1: You cannot use an instance variable to initialize another instance variable. Why? Because the compiler can rearrange these - there is no guarantee that variable "a" will be initialized before "b", so the above line might throw a NullReferenceException.
Answer2: It works fine with static because static are initialize before other variables and their references are not changed.
Please let me know if it helps.
As Anirudh said. You cannot use an instance variable to initialize another instance variable. Why? Because the compiler can rearrange these - there is no guarantee that a will be initialized before b.
You can use constructor for this.
class Tester
{
public int a=5;
public int b;
public Tester()//constructor
{
b=a;
}
}
or
class Tester
{
public static int a = 5;
public static int b;
public Tester()//constructor
{
b = a;
}
}

What is the use of static variable in C#? When to use it? Why can't I declare the static variable inside method?

I have searched about static variables in C#, but I am still not getting what its use is. Also, if I try to declare the variable inside the method it will not give me the permission to do this. Why?
I have seen some examples about the static variables. I've seen that we don't need to create an instance of the class to access the variable, but that is not enough to understand what its use is and when to use it.
Second thing
class Book
{
public static int myInt = 0;
}
public class Exercise
{
static void Main()
{
Book book = new Book();
Console.WriteLine(book.myInt); // Shows error. Why does it show me error?
// Can't I access the static variable
// by making the instance of a class?
Console.ReadKey();
}
}
A static variable shares the value of it among all instances of the class.
Example without declaring it static:
public class Variable
{
public int i = 5;
public void test()
{
i = i + 5;
Console.WriteLine(i);
}
}
public class Exercise
{
static void Main()
{
Variable var1 = new Variable();
var1.test();
Variable var2 = new Variable();
var2.test();
Console.ReadKey();
}
}
Explanation: If you look at the above example, I just declare the int variable. When I run this code the output will be 10 and 10. Its simple.
Now let's look at the static variable here; I am declaring the variable as a static.
Example with static variable:
public class Variable
{
public static int i = 5;
public void test()
{
i = i + 5;
Console.WriteLine(i);
}
}
public class Exercise
{
static void Main()
{
Variable var1 = new Variable();
var1.test();
Variable var2 = new Variable();
var2.test();
Console.ReadKey();
}
}
Now when I run above code, the output will be 10 and 15. So the static variable value is shared among all instances of that class.
C# doesn't support static local variables (that is, variables that are declared in method scope).
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members#static-members
You can declare static fields (class members) though.
Reasoning: Static field is a state, shared with all instances of particular type. Hence, the scope of the static field is entire type. That's why you can't declare static instance variable (within a method) - method is a scope itself, and items declared in a method must be inaccessible over the method's border.
static variables are used when only one copy of the variable is required. so if you declare variable inside the method there is no use of such variable it's become local to function only..
example of static is
class myclass
{
public static int a = 0;
}
Variables declared static are commonly shared across all instances of a class.
Variables declared static are commonly shared across all instances of a class. When you create multiple instances of VariableTest class This variable permanent is shared across all of them. Thus, at any given point of time, there will be only one string value contained in the permanent variable.
Since there is only one copy of the variable available for all instances, the code this.permament will result in compilation errors because it can be recalled that this.variablename refers to the instance variable name. Thus, static variables are to be accessed directly, as indicated in the code.
Some "real world" examples for static variables:
building a class where you can reach hardcoded values for your application. Similar to an enumeration, but with more flexibility on the datatype.
public static class Enemies
{
public readonly static Guid Orc = new Guid("{937C145C-D432-4DE2-A08D-6AC6E7F2732C}");
}
The widely known singleton, this allows to control to have exactly one instance of a class. This is very useful if you want access to it in your whole application, but not pass it to every class just to allow this class to use it.
public sealed class TextureManager
{
private TextureManager() {}
public string LoadTexture(string aPath);
private static TextureManager sInstance = new TextureManager();
public static TextureManager Instance
{
get { return sInstance; }
}
}
and this is how you would call the texturemanager
TextureManager.Instance.LoadTexture("myImage.png");
About your last question:
You are refering to compiler error CS0176. I tried to find more infor about that, but could only find what the msdn had to say about it:
A static method, field, property, or event is callable on a class even
when no instance of the class has been created. If any instances of
the class are created, they cannot be used to access the static
member. Only one copy of static fields and events exists, and static
methods and properties can only access static fields and static
events.
Static variables are used when only one copy of it is required. Let me explain this with an example:
class circle
{
public float _PI =3.14F;
public int Radius;
public funtionArea(int radius)
{
return this.radius * this._PI
}
}
class program
{
public static void main()
{
Circle c1 = new Cirle();
float area1 = c1.functionRaduis(5);
Circle c2 = new Cirle();
float area2 = c1.functionRaduis(6);
}
}
Now here we have created 2 instances for our class circle , i.e 2 sets of copies of _PI along with other variables are created. So say if we have lots of instances of this class multiple copies of _PI will be created occupying memory. So in such cases it is better to make such variables like _PI static and operate on them.
class circle
{
static float _PI =3.14F;
public int Radius;
public funtionArea(int radius)
{
return this.radius * Circle._PI
}
}
class program
{
public static void main()
{
Circle c1 = new Cirle();
float area1 = c1.functionRaduis(5);
Circle c2 = new Cirle();
float area2 = c1.functionRaduis(6);
}
}
Now no matter how many instances are made for the class circle , only one copy exists of variable _PI saving our memory.
Static classes don't require you to create an object of that class/instantiate them, you can prefix the C# keyword static in front of the class name, to make it static.
Remember: we're not instantiating the Console class, String class, Array Class.
class Book
{
public static int myInt = 0;
}
public class Exercise
{
static void Main()
{
Book book = new Book();
//Use the class name directly to call the property myInt,
//don't use the object to access the value of property myInt
Console.WriteLine(Book.myInt);
Console.ReadKey();
}
}
The data members and function members that operate on the instance of the type
are called instance members. The int’s ToString method (for example) are examples of instance members. By default, members are instance members.
Data members and function members that don’t operate on the instance of the type, but rather on the type itself, must be marked as static. The Test.Main and Console.WriteLine methods are static methods. The Console class is actually a static class, which means all its members are static. You never actually create instances of a Console—one console is shared across the whole application.
In response to the "when to use it?" question:
I often use a static (class) variable to assign a unique instance ID to every instance of a class. I use the same code in every class, it is very simple:
//Instance ID ----------------------------------------
// Class variable holding the last assigned IID
private static int xID = 0;
// Lock to make threadsafe (can omit if single-threaded)
private static object xIDLock = new object();
// Private class method to return the next unique IID
// - accessible only to instances of the class
private static int NextIID()
{
lock (xIDLock) { return ++xID; }
}
// Public class method to report the last IID used
// (i.e. the number of instances created)
public static int LastIID() { return xID; }
// Instance readonly property containing the unique instance ID
public readonly int IID = NextIID();
//-----------------------------------------------------
This illustrates a couple of points about static variables and methods:
Static variables and methods are associated with the class, not any specific instance of the class.
A static method can be called in the constructor of an instance - in this case, the static method NextIID is used to initialize the readonly property IID, which is the unique ID for this instance.
I find this useful because I develop applications in which swarms of objects are used and it is good to be able to track how many have been created, and to track/query individual instances.
I also use class variables to track things like totals and averages of properties of the instances which can be reported in real time. I think the class is a good place to keep summary information about all the instances of the class.
Try calling it directly with class name Book.myInt
On comparison with session variables, static variables will have same value for all users considering i am using an application that is deployed in server. If two users accessing the same page of an application then the static variable will hold the latest value and the same value will be supplied to both the users unlike session variables that is different for each user. So, if you want something common and same for all users including the values that are supposed to be used along the application code then only use static.
You don't need to instantiate an object, because yau are going to use
a static variable:
Console.WriteLine(Book.myInt);
Static variable retains it's previous value until the program exit. Static is used by calling directly class_Name.Method() or class_Name.Property. No object reference is needed. The most popular use of static is C#'s Math class.
Math.Sin(), Math.Cos(), Math.Sqrt().

Categories