This question already has answers here:
Initialization Order of Static Fields in Static Class
(3 answers)
Closed 4 years ago.
Will it always works correctly?
public class Test
{
public static List<int> a = new List<int>{1,2,3};
public static List<int> b = new List<int>(a);
}
Because when I switched them
public class Test
{
public static List<int> b = new List<int>(a);
public static List<int> a = new List<int>{1,2,3};
}
then I received
Exception in user code:
System.ArgumentNullException: Value cannot be null.
Parameter name: collection
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at .Test..cctor()
Are there any other things I have to worry about?
If you need deterministic initialization, use a static constructor:
public static List<int> a;
public static List<int> b;
private static Test()
{
a = new List<int>{1,2,3};
b = new List<int>(a);
}
The C#/CLR specification ensures the order in which field initializers are executed, but as you've noticed, if you mess up the ordering of your fields in the class, things break down at runtime. That's a bad idea regardless of the contractual behavior, given how easy it is to switch the order of fields in a class.
So my advice is: if the field initializers don't depend on other fields, keep them. If they do, put the initialization in a constructor, where the ordering is very explicit.
The relevant quote from specification:
If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor (ยง17.4.5).
So you can rely on the textual order contractually, but I'd still recommend against it. It's way too easy to break, and people usually don't consider the order of members in the code file of a class important. It would be fine if you got a compilation error, but you don't - if you're lucky, you get a runtime error. If you're not, you're going to be scratching your head with "impossible" situations that had nothing to do with your changes (right?).
Yes as you have observed correctly the order has to remain as below since the member fields will get initialized in accordance order
public static List<int> a = new List<int>{1,2,3};
public static List<int> b = new List<int>(a);
Related
Hi I am new to C# and I am aware on a surface level that I cannot use non static fields inside static methods. But I have a situation that I am trying to understand conceptually.
Check out this code snippet:
class CIMConversionHelper
{
private static Logger Logger = LogManager.GetCurrentClassLogger();
private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
public static TDX2KlarfResult HandleConversion(TDXProcessItem item, string fileName)
{
TDX2KlarfResult result = new TDX2KlarfResult();
result.success = true;
XmlDocument doc = new XmlDocument();
try
{
doc.Load(fileName);
}
catch (Exception ex)
{
result.success = false;
Logger.Error(ex, "XML Parsing Error: ");
return result;
}
_procEndTimeData.ToolType = toolType;
_procEndTimeData.Lot = input.cimToolContext.LOT;
_procEndTimeData.WaferScribe = input.cimWaferContainer.waferContext.WAFER_SCRIBE;
_procEndTimeData.Processing_End_Time = input.cimToolContext.PROCESSING_END_TIME;
}
public static TDX2KlarfResult Convert(TDXProcessItem item, string fileName)
{
TDX2KlarfResult result = new TDX2KlarfResult();
result.success = true;
try
{
result = CIMConversionHelper.HandleConversion(item, fileName);
}
catch (Exception ex)
{
// Failed to Parse the xml Not good mark nonrecoverable error and return.
result.errorType = "Non-Recoverable";
result.success = false;
Logger.Error(ex, "Unknown Error: ");
return result;
}
if (result.success)
{
//DBHelper.AddProcessingEndTimeToDB();
}
return result;
}
}
This is a very abridged snippet but one that captures my question. I have created an object reference as field for ProcessingEndTimeData called _procEndTimeData.
Why then is it telling me in Visual Studio that:
"an object reference is required for the non-static field, method, or property CIMConversionHelper._procEndTimeData?
I thought I should be able to assign values to the declared object "_procEndTimeData" in the 4th line inside the static function "HandleConversion"
Can someone explain to me why this reference is not enough? and why I would then have to create yet another ProcessingEndTimeData object inside the static function HandleCOnversion?
I know I can just toggle _procEndTimeData to be static but why do I need to do this if I have already created a reference in the field level?
Think about the memory of the equipment.
When you create an object, memory is reserved for it. Imagine, that because of its properties (int, char...) it occupies 32 bytes. If you create 10 objects, you will have 320 bytes occupied in memory for your objects.
But when you use "static", those properties are created only once for the class. Not once for each object you create.
So, your 10 objects can access their own properties (int, char...) and also the static ones. But from a "static" method you cannot access the properties of an object of that class because you don't have the instance of it.
A very simple example: You have a User class with the Name property. You add a static variable of type integer: static int count. That variable will be used to record the number of users you create.
In the constructor of the user you can do count++ because the instances of the class can access to the properties of the class. But if you create a static method:
public static void DoSomething()
{
// You can show a message with the number of users
MessageBox.Show(count.ToString());
// But you CAN'T access to a "Name" because this method is not
// a method of one concrete user. It's a general method, for all users
}
If you invoke DoSomething and you are created two users, "Tom" and "Jerry", in DoSomething you don't know any user.
You have 2 choices to make this work. Not sure which one applies. My guess is the first one I will show
private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
change to
static private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
This says that this field is also static, ie belongs to the class, not to instances of the CIMConversionHelper class.
The alternative, which I dont think you want it to create an instance of CIMConversionHelper in that method. Which as I said is probably not what you want.
If your intent is that this class (CIMConversionHelper) is all static, ie you will never create an instance of it then mark the class itself static and the compiler will ensure that you dont accidentally create non static members. ie
static class CIMConversionHelper{....}
Why is this so?
You say you have created a reference here
private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
YOu have not created it yet.
You need to understand the difference between static and instance functions and fields.
Lets have an example. We have a class Thingy. It includes a factory method that makes thingy instances and keeps a count of how many it has made
public class Thingy{
static s_thingyCount = 0;
string _froop;
public static CreateThingy(){
var thing = new Thingy();
......
s_thingyCount++;
thing._froop = "hello";
return thing;
}
public void Twang(int froop){
......
}
public int Oink(string pling){
......
_froop = pling;
}
}
we can go
var t1 = Thingy.CreateThingy();
t1.Oink("Ole");
The CreateThingy does not operate on instances of the class, it operates on the class itself. The count variable does not belong to an instance, it belongs to the class itself. Note that in the create method we have to say
thing._froop = "hello";
ie which objects _froop we want to set (the one we are in the process of making).
var t1 = Thingy.CreateThingy();
now we have an instance of Thingy we can call methods on it
t1.Oink("Ole");
Look in that method
public int Oink(string pling){
......
_froop = pling;
}
we dont say which froop to set, we are manipulating an instance of the class.
We cannot do
Thingy.Oink("xxx");
Which THingy would be updates? Nor can we do
Thingy._froop = "fff";
for the same reason
but we can do
var count = Thingy.s_thingyCount;
How does this map to your class. THis method is static. It is like CreateThingy, it does not have an instance to operate on.
public static TDX2KlarfResult HandleConversion(TDXProcessItem item, string fileName)
but you do this
_procEndTimeData.ToolType = toolType;
with this field
private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
this is just like doing
_froop = "hello"
in CreateThingy
_proceEndTimeData only exists in instances on your class.
It will be create when you do
new CIMConversionHelper();
But I suspect thats not what youo want to do. So you need to make _proceEndTimeData static, just like s_thingyCount
If I'm understanding it correctly, you answered yourself: "I am aware on a surface level that I cannot use non static fields inside static methods", and then you have declared a non static variable inside your method:
private readonly ProcessingEndTimeData _procEndTimeData
It should be static, apart than readonly if you want.
The reason for this has to do with object oriented programming. To access a static method from a class you don't need to instantiate it. This is why you can't reference class-level non static variables inside a static method from that class. Hope that made it a little clearer.
I know I can just toggle _procEndTimeData to be static but why do I need to do this if I have already created a reference in the field level?
You created no such thing, your _procEndTimeData is a field in every instance of CIMConversionHelper, of which you have none.
If it helps you visualize the problem better, imagine what would happen if your expectation was reality and you had the following code:
CIMConversionHelper h1 = new(), h2 = new();
CIMConversionHelper.Convert(.....whatever....);
Would it change h1._procEndTimeData? h2._procEndTimeData? It has to pick one, right? So which one does it pick?
No. static methods can only use static fields, period.
This question already has answers here:
static property in c# 6
(3 answers)
Closed 4 years ago.
I apologize for a really bad title. I don't know the correct terminology, but will edit it if you can inform me what I am actually asking.
Is it possible to do the following in one row, like with an auto-property?:
public class MyClass
{
static OtherClass _otherClass;
static OtherClass otherClass => _otherClass ?? (_otherClass = new OtherClass());
}
You could use Lazy<T> for lazy initialization, although it does not simplify the code too much:
static Lazy<OtherClass> _otherClassLazy = new Lazy<OtherClass>(() => new OtherClass());
static OtherClass otherClass => _otherClassLazy.Value;
Lazy<T> initializes the value only once, and only when actually accessed.
If you really want a single line, you can use:
static Lazy<OtherClass> otherClass { get; } = new Lazy<OtherClass>(() => new OtherClass());
At the cost of having to use otherClass.Value when referring to this variable in code.
This solution is preferable to the { get; } = new OtherClass() in case you want to initialize the property only on-demand, not during the initialization of the class itself. This may be desirable in case the constructor is doing a lot of work and the property might not be used in some cases.
My example:
class MyClass
{
public int a = 1;
public static List<MyClass> list = new List<MyClass>();
}
class Program
{
static void Main(string[] args)
{
MyClass.list.Add(new MyClass() { a = 5 });
MyClass.list.Add(new MyClass() { a = 10 });
foreach (MyClass item in MyClass.list) Console.WriteLine(item.a);
Console.ReadKey();
}
This code works, and shows that my list, which is statically defined within the MyClass class itself, is populating as I'd expect.
Is there any reason not to define my list in this manner?
Such a solution is used sometime, f.e. to implement the Singleton or Register-Resolve patterns.
But you should keep in mind that it's not well suited for multithread environment. Typically, a static collection should be private, and access methods (including property getter and setter) should be synchronized.
In additional, static fields/properties are difficult to an unit testing.
Actually this code shows a lot of sign of (very) bad desing.
First of all one better doesn't make fields public. All other classes/object can now alter the value of that variable in objects. Perhaps you don't see much problems with that, but imagine that at one point in time you want to restrict the range of values that variable can have, or that it depends on the value of another field. Properties (with getters and setters) and methods are used to shield an field from external usage, they need to guarantee that the object always remains in a valid state.
Next about the list, again don't make such lists public - unless you are confident that there is no problem -. But furthermore using statics is by some researchers considered to be bad design as well. The list maintains a state, but since it is static, this is a global state. Global states are problematic since they don't allow (easy) unit testing, and can become problematic if for some reason the list should be not that global.
In case you really want to make some access point for data, you can perhaps consider making a class that stores such list and pass it around in your program.
There are a few exceptions, for instance the Flyweight pattern where one indeed maintains a global state. Those examples are merely used to increase performance. For instance:
public class FlyWeightInstance {
private int value; //<- private field
private static Dictionary<int,FlyWeightInstance> dic = new Dictionary<int,FlyWeightInstance>(); //<- private static cache
private int FlyWeightInstance (int value) { // <-- private constructor
this.value = value;
}
public static FlyWeightInstance (int value) {
FlyWeightInstance res;
if(!dic.TryGetValue(value,out res)) {
res = new FlyWeightInstance(value);
dic.Add(value,res);
}
return res;
}
}
I've been looking for a decent definition of static arrays. I've tried using msdn and c# sources but cannot seem to find a definition. It gives examples, but no definitions...
Does anyone know any links or definitions and characteristics of a static array please?
When you talk about a 'static array' you are really talking about two separate things.
One would be the static keyword. When applied to variables this means that the variable lives at the class level, and each object of that type will not get its own instance.
An array is simply a data structure for holding multiple values of some type.
So, a static array is simply an array at the class level that can hold multiple of some data type.
For example:
In your TravelRoute class, you may have a set number of possible destinations in a route. These could be defined like so:
class TravelRoute {
public static Destination[] possibleDestinations =
new Destination[]{
new Destination("New York"),
new Destination("Minneapolis"),
new Destination("NParis")
};
}
This will define the possible destinations on a TravelRoute. You can then access the array like so:
Destination one = TravelRoute.possibleDestinations[0];
Do you possibly mean fixed size arrays?
unsafe struct Foo
{
fixed int Values[8];
}
If so, you will get more search results by using fixed size arrays as your query :)
There's nothing (that I know of) that's special about static arrays, per se, which may be why you're having trouble finding good write-ups about them. Correct me if I'm wrong, but I wonder if it's the "static" part that you're most interested in? Basically, static means that the member exists at the class level rather than the instance level, so a static array would be an array that belongs to the class (rather than an instance of the class).
Example:
public class Foo
{
public static int[] Numbers {get; set;}
}
public class Bar
{
public int[] Numbers {get;set;}
}
public class Program
{
public void Main()
{
// NOTE: Foo itself has this array
Foo.Numbers = new int[]{1,2,3};
// NOTE: it's this particular instance of a Bar that has this array
Bar bar = new Bar();
bar.Numbers = new int[]{1,2,3};
}
}
Use the static modifier to declare a
static member, which belongs to the
type itself rather than to a specific
object.
???
My encounter with this static keyword occurred when I defined a variable public int abc. When the value of this variable changed withing the brackets of while, or within the brackets of if, or within the brackets of methods, these changes were not valid, were not reflected, were not know outside the brackets. So just a hit trial. I made the variable static and all problems solved.
But why??
The difference between a static and a non-static member (not variable) is that a static member is unique over the whole runtime of a program (i.e. there is only one static member instance) whereas a non-static member is associated with an object instance (i.e. there is a member instance for each instance of the corresponding object). This is in a bit more words what the definition says.
How this all applies to what you wrote in regard to changes not reflected im not too sure - maybe you should post the corresponding code.
I did not understand what you meant but
static variables are variables at the class level - they do not belong to an instance of an object but to the class itself. They can be used and accessed without instantiating any instance.
An instance (non static) variable on the other hand belongs to the instance itself.
If you have a class:
public class Car {
public static readonly int Wheels = 4;
public static int Count {get;set;}
public string Make {get;set;}
public string Model {get;set;}
public int Year {get;set;}
public Car() { Car.Count = Car.Count + 1; }
public string SoundOff(){
return String.Format("I am only 1 out of {0} car{1}",
Car.Count, (Car.Count > 0 ? "s" : String.Empty));
}
}
Then, every time you create a car, the count will increase by one. This is because the Count property belongs to the Car class, and not to ever object you've created.
This is also useful because every car can have knowledge of the Car.Count. So, if you created:
Car sportster = new Car {
Make="Porsche", Model="Boxster", Year=2010 };
sportster.SoundOff(); // I am only 1 out of 1 car
You can do other processing and Count will be known to all objects:
Car hybrid = new Car { Make="Toyota", Model="Prius", Year=2010 };
hybrid.SoundOff(); // I am only 1 out of 2 cars
sportster.SoundOff(); // I am only 1 out of 2 cars
So, in other words, you should use static when you want something to:
Be accessible at the class-level so all objects know of it (Car.Count instead of hybrid.Count)
Represent the class and not the object (Car.Wheels won't change)
There are other reasons to use static, like Utility classes, extension methods, etc. But this should answer your question about the MSDN wording.
It's probably because you're creating multiple copies of the class, and each class has its own values for that member.
By change it to static, all instances share the same copy of the member variable.
The behavior that you're observing probably indicates a problem in your while and if expressions. If you post some sample code, I might be able to help further.