Accessing static class variables via instantiated objects - c#

So I came upon some legacy C# code that has a class with some static variables in it.
public class TMP_PARAM
{
// stores params and signals of test
public static List<filter> data_p;
public static List<filter> data_p_save;
public static List<filter> data_s;
public static List<filter> data_s_save;
public List<filter> data_operation_p
{
get
{
return data_p;
}
set
{
data_p = value;
}
}
However I was confused when they had data in them even though there was no point in the code where they were set ie:
Automobile.Drive();
int i = Automobile.NumberOfWheels;
I found out that the variables were being set by different objects via set calls
TMP_PARAM tmp = new TMP_PARAM();
tmp.data_operation_p = cast_list;
My question is why does the C# compiler allow this? Shouldn't static class variables only be accessed via a class interface?

You are confusing access modifiers with static. The code marks them as public, so they are accessible from the outside. Mark them as private and the initialization will then have to be inside the class definition.

Related

C# Unity > Static instance member not causing constructor to be called

I have noticed a rather weird behaviour in my application I am creating;
I have a class I defined that has a static "instance" variable of the class type.
I would assume that (as per code attached) the constructor would be called.
Alas, it is not, unless I use the Void.get in a non-static field anywhere in my code.
public class Void : TilePrototype {
public static Tile get = new Tile((int)TileEntities.Void);
public static Void instance = new Void();
public Void() {
Debug.Log("created");
id = (int)TileEntities.Void;
isBlocking = true;
register();
}
public override RenderTile render(Tile tile){
return new RenderTile(0, new Color(0, 0, 0, 0));
}
So when I have something like :
public static TileStack empty = new TileStack(Void.get, Void.get);
the Void class constructor never gets called. But, if I have:
Tile t = Void.get;
Anywhere in my code it will be called.
Why?
Thanks.
This is a really really subtle and nuanced area of C#; basically, you've stumbled into "beforefieldinit" and the difference between a static constructor and a type initializer. You can reasonably ask "when does a static constructor run?", and MSDN will tell you:
It is called automatically before the first instance is created or any static members are referenced.
Except... public static TileStack empty = new TileStack(Void.get, Void.get); isn't a static constructor! It is a static field initializer. And that has different rules, which basically are "I'll run when I must, no later, possibly sooner". To illustrate with an example: the following will not (probably) run your code, because it doesn't have to - there isn't anything demanding the field:
class Program
{
static void Main()
{
GC.KeepAlive(new Foo());
}
}
public class Foo
{
public static TileStack empty = new TileStack(Void.get, Void.get);
}
However, if we make a tiny tweak:
public class Foo
{
public static TileStack empty = new TileStack(Void.get, Void.get);
static Foo() { } // <=== added this
}
Now it has a static constructor, so it must obey the "before the first instance is created" part, which means it needs to also run the static field initializers, and so on and so on.
Without this, the static field initializer can be deferred until something touches the static fields. If any of your code actually touches empty, then it will run the static field initializer, and the instance will be created. Meaning: this would also have this effect:
class Program
{
static void Main()
{
GC.KeepAlive(Foo.empty);
}
}
public class Foo
{
public static TileStack empty = new TileStack(Void.get, Void.get);
}
This ability to defer execution of the static initialization until the static fields are actually touched is called "beforefieldinit", and it is enabled if a type has a static field initializer but no static constructor. If "beforefieldinit" isn't enabled, then the "before the first instance is created or any static members are referenced" logic applies.
Thanks to Marc Gravell's aswer I came up with this contraption (and admittedly I do like the new solution more than the old one, so thanks again!)
Modifications done to the Void class:
public class Void : TilePrototype {
public static Void instance = new Void();
public static Tile get {
get {
return new Tile(instance.id);
}
}
public Void() {
isBlocking = true;
}
public override RenderTile render(Tile tile){
return new RenderTile(0, new Color(0, 0, 0, 0));
}
}
So as You can see I made the "get" variable a property, so that it's evaluated later, when you actually need the tile, not on construction.
I've changed all "get"s this way.
Second change is in the TilePrototype:
public class TilePrototype {
public static Dictionary<int, TilePrototype> tilePrototypeDictionary = new Dictionary<int, TilePrototype>();
public static void registerPrototype(int id, TilePrototype tp){
tp.id = id;
tilePrototypeDictionary.Add(id, tp);
}
public static bool registered = false;
public static void registerAll(){
if( registered ) return;
registerPrototype(0, Void.instance);
registerPrototype(1, Air.instance);
registerPrototype(2, Floor.instance);
registerPrototype(3, Wall.instance);
(...)
Here I've added the registerPrototype and registerAll functions.
This gives me easy access to all the registered type ids (by say Wall.instance.id) as well as the other way around (from id to instance via the Dictionary)
I also have all registered things in one place, with the possibility of runtime adding more
Overall, much neater, and here I assure that all tiles are registered properly and assigned proper IDs.
Change of ID is simple and in one place and everywhere else, access to this ID is done via a short .instance.id
Thanks again for the help :)

How to return class instance from static class?

I want use a static class that must contains global variables, so I can access to all application controls simply from a variable.
Actually I've this implementation:
public static class Globals
{
public static HeadToHead Head2Head
{
get { return Resources.Controls.HeadToHead; }
}
}
in the case above, I want return the instance of HeadToHead control, the control look like this:
public partial class HeadToHead : UserControl
{
public static int HomeId = 0;
}
my goal is to access to the static variables of this control, like: Globals.Head2Head.HomeId
but I get this error on this line: get { return Resources.Controls.HeadToHead; }
HeadToHead is a type which is not valid in the given context
You're returning what looks like a type from a property that seems to be declaring an instance of that type. If you truly want to return that type, there's syntax for that (I don't remember any more, I think in c# it's classname.type). If you want to return an instance, then you need to get that instance from somewhere.
As an aside, static instances of UI controls are a bad idea, and a code smell.
You have to instantiate an instance of the type and return that. As you want a single global instance you could use the static constructor.
public static class Globals {
static Globals(){
Head2Head = new Resources.Controls.HeadToHead();
}
public static HeadToHead Head2Head { get; private set; }
}
There are few situations in which you would actually want to do this but common static settings that do not change in the life of the application might be one of them. As HeadToHead inherits from UserControl that does not really seem to be the case, an instance of a UserControl should ideally never be static.

Accessing to a property of a non-static class in any place

I come today with a weird question.
Is there a way where I can use a non static class like static?
I.e:
We have the following classes:
public class Parameters
{
public String LoadType { get; set; }
public Parameters (String inLoadType)
{
LoadType = inLoadType;
}
}
public class MainClass
{
public Parameters Parameters { get; set; }
public MainClass(String inLoadType)
{
Parameters = new Parameters(inLoadType);
}
}
Now we instantiate MainClass, then somewhere in another place that is not the MainClass I would like to access to the LoadType.
It should be threadSafe, also the operation take quite long, that is the reason I cannot simply just use a lock and make it static.
The class where I want to access that variable is static, I thought in a workaround with a static Event in the Parameters class, and whoever call the event would get the value of the instantiated class or something like that.
Any other Ideas about it beside passing as parameter to the static method what I need?
Sounds like stupid question but I just want to know if is possible or not.
Imagine, that you have two Parameters instances
Parameters one = new Parameters("One");
Parameters two = new Parameters("Two");
and then you call:
String result = SomeWeirdBlackMagicCallOfLoadType();
What is the expected result? "One" or "Two"? In order to solve this
problem, you can turn Parameters into singletone (one instance only) and thus the call will be
String result = Parameters.Instance.LoadType;
but I suggest treating static as static when data doesn't depend on instance. In case of long operations, thread safety you can use Lazy<String> which is specially designed for that:
public class Parameters {
private static Lazy<String> s_LoadType = new Lazy<string>(() => {
....
return "bla-bla-bla";
});
public static String LoadType {
get {
return s_LoadType.Value;
}
}
...
}

how to define a Global Structure in C#?

I want to define a global structure in C# and use it in three separate subroutines. I have already created the structure but I don't know how to make it a global variable so I can use it in multiple sections of my code. Any help is appreciated.
public struct Simple
{
public int Position;
public bool Exists;
public double LastValue;
};
static void Main(string[] args)
{
Simple s;
s.Position = 1;
s.Exists = false;
s.LastValue = 5.5;
}
So I want to use a Simple structure in two other routines in my code and possible pass it to different form (multiple usage of one variable).
The closest thing to "global" in C# is "static". Simply define the class and all members as static and it'll be accessible from anywhere the containing namespace is referenced. EDIT as Servy correctly points out, the class itself does not have to be static; however doing so forces all members to be static at compile-time. Also, static members can have any visibility, so you can have a private static field used by a public static property or method, and you can have an internal static class that won't be visible outside its home assembly. Just being static doesn't automatically make it wide open.
However, a better pattern might be the Singleton; you define a class that has one static instance of itself, that can then be passed around. The benefit is that you can still deal with the object as an instance class if you want to, but the same instance is available everywhere using a static getter. Here's some reading material: http://csharpindepth.com/Articles/General/Singleton.aspx
In your case it appears that you have a object as a local variable in your main method that you need to use in another method. The appropriate solution in this context is to add a parameter to that other method. Take a look at this example:
public class MyObject
{
public int Value;
}
public static void Main(string[] args)
{
MyObject obj = new MyObject();
obj.Value = 42;
PrintObject(obj);
Console.WriteLine("Press any key to exit...");
Console.ReadKey(true);
}
public static void PrintObject(MyObject obj)
{
Console.WriteLine(obj.Value);
}

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