Why can't non-static fields be initialized inside structs? - c#

Consider this code block:
struct Animal
{
public string name = ""; // Error
public static int weight = 20; // OK
// initialize the non-static field here
public void FuncToInitializeName()
{
name = ""; // Now correct
}
}
Why can we initialize a static field inside a struct but not a non-static field?
Why do we have to initialize non-static in methods bodies?

Have a look at Why Can't Value Types have Default Constructors?

The CLI expects to be able to allocate and create new instances of any value type that would require 'n' bytes of memory, by simply allocating 'n' bytes and filling them with zero. There's no reason the CLI "couldn't" provide a means of specifying either that before any entity containing structs is made available to outside code, a constructor must be run on every struct therein, or that a whenever an instance of a particular n-byte struct is created, the compiler should copy a 'template instance'. As it is, however, the CLI doesn't allow such a thing. Consequently, there's no reason for a compiler to pretend it has a means of assuring that structs will be initialized to anything other than the memory-filled-with-zeroes default.

You cannot write a custom default constructor in a structure. The instance field initializers will eventually need to get moved to the constructor which you can't define.
Static field initializers are moved to a static constructor. You can write a custom static constructor in a struct.

You can do exactly what you're trying. All you're missing is a custom constructor that calls the default constructor:
struct Animal
{
public string name = "";
public static int weight = 20;
public Animal(bool someArg) : this() { }
}
The constructor has to take at least one parameter, and then it has to forward to this() to get the members initialised.
The reason this works is that the compiler now has a way to discover the times when the code should run to initialise the name field: whenever you write new Animal(someBool).
With any struct you can say new Animal(), but "blank" animals can be created implicitly in many circumstances in the workings of the CLR, and there isn't a way to ensure custom code gets run every time that happens.

Related

in C# why static fields are not initialized after creating first instance of that type (in case of having no static constructor) [duplicate]

DependencyProperty.AddOwner MSDN page offers an example with two classes with static members, and the member of one class depends on the member of the other class for initialization. I think MSDN is wrong - the initialization order of static variables is unreliable in C# just like it is in C++ or anywhere else. I'm probably wrong because the WPF library itself is written that way and it works just fine. What am I missing? How can C# compiler possibly know the safe initialization order?
It's fine for one type to depend on another type being initialized, so long as you don't end up in a cycle.
Basically this is fine:
public class Child
{
static Child() {} // Added static constructor for extra predictability
public static readonly int X = 10;
}
public class Parent
{
static Parent() {} // Added static constructor for extra predictability
public static readonly int Y = Child.X;
}
The result is well-defined. Child's static variable initializers are executed prior to the first access to any static field in the class, as per section 10.5.5.1 of the spec.
This isn't though:
public class Child
{
public static readonly int Nasty = Parent.Y;
public static readonly int X = 10;
}
public class Parent
{
public static readonly int Y = Child.X;
}
In this latter case, you either end up with Child.Nasty=0, Parent.Y=10, Child.X=10 or Child.Nasty=0, Parent.Y=0, Child.X=10 depending on which class is accessed first.
Accessing Parent.Y first will start initializing Parent first, which triggers the initialization of Child. The initialization of Child will realise that Parent needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the first set of numbers - because Child.X ends up being initialized before its value is used for Parent.Y.
Accessing Child.Nasty will start initializing Child first, which will then start to initialize Parent. The initialization of Parent will realise that Child needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the second set of numbers.
Don't do this.
EDIT: Okay, more detailed explanation, as promised.
When is a type initialized?
If a type has a static constructor, it will only be initialized
when it's first used (either when a static member is referenced, or
when an instance is created). If it doesn't have a static
constructor, it can be initialized earlier. In theory, it could also
be initialized later; you could theoretically call a constructor or
a static method without the static variables being initialized - but
it must be initialized before static variables are referenced.
What happens during initialization?
First, all static variables receive their default values (0, null
etc).
Then the static variables of the type are initialized in textual
order. If the initializer expression for a static variable requires
another type to be initialized, then that other type will be
completely initialized before the variable's value is assigned -
unless that second type is already being initialized (due to a
cyclic dependency). Essentially, a type is either:
Already initialized
Being initialized at the moment
Not initialized
Initialization is only triggered if the type is not initialized.
This means that when there are cyclic dependencies, it is possible
to observe a static variable's value before its initial value has
been assigned. That's what my Child/Parent example shows.
After all the static variable initializers have executed, the static
constructor executes.
See section 10.12 of the C# spec for more details on all of this.
By popular demand, here was my original answer when I thought the question was about the initialization order of static variables within a class:
Static variables are initialized in textual order, as per section 10.5.5.1 of the C# spec:
The static field variable initializers
of a class correspond to a sequence of
assignments that are executed in the
textual order in which they appear in
the class declaration.
Note that partial types make this trickier as there's no one canonical "textual order" of the class.
If you are concerned about the order you could always place your code in the static constructor. This is where I register my dependency properties.
No I think unreliable is not the correct word here.
In true single thread scenario, static members of class are initialized when any of static members of the type is first accessed in your code.
I am not aware of c++, but yes only in certain cases like in Multi threaded environment if two types trying to access shared resource and if that is static then its impossible to tell who will win and which one will work correct.
The MSDN Example is correct and that will work correctly.

C# initial value in constructor OR class variable declaration? [duplicate]

I've been programming in C# and Java recently and I am curious where the best place is to initialize my class fields.
Should I do it at declaration?:
public class Dice
{
private int topFace = 1;
private Random myRand = new Random();
public void Roll()
{
// ......
}
}
or in a constructor?:
public class Dice
{
private int topFace;
private Random myRand;
public Dice()
{
topFace = 1;
myRand = new Random();
}
public void Roll()
{
// .....
}
}
I'm really curious what some of you veterans think is the best practice. I want to be consistent and stick to one approach.
My rules:
Don't initialize with the default values in declaration (null, false, 0, 0.0…).
Prefer initialization in declaration if you don't have a constructor parameter that changes the value of the field.
If the value of the field changes because of a constructor parameter put the initialization in the constructors.
Be consistent in your practice (the most important rule).
In C# it doesn't matter. The two code samples you give are utterly equivalent. In the first example the C# compiler (or is it the CLR?) will construct an empty constructor and initialise the variables as if they were in the constructor (there's a slight nuance to this that Jon Skeet explains in the comments below).
If there is already a constructor then any initialisation "above" will be moved into the top of it.
In terms of best practice the former is less error prone than the latter as someone could easily add another constructor and forget to chain it.
I think there is one caveat. I once committed such an error: Inside of a derived class, I tried to "initialize at declaration" the fields inherited from an abstract base class. The result was that there existed two sets of fields, one is "base" and another is the newly declared ones, and it cost me quite some time to debug.
The lesson: to initialize inherited fields, you'd do it inside of the constructor.
The semantics of C# differs slightly from Java here. In C# assignment in declaration is performed before calling the superclass constructor. In Java it is done immediately after which allows 'this' to be used (particularly useful for anonymous inner classes), and means that the semantics of the two forms really do match.
If you can, make the fields final.
Assuming the type in your example, definitely prefer to initialize fields in the constructor. The exceptional cases are:
Fields in static classes/methods
Fields typed as static/final/et al
I always think of the field listing at the top of a class as the table of contents (what is contained herein, not how it is used), and the constructor as the introduction. Methods of course are chapters.
In Java, an initializer with the declaration means the field is always initialized the same way, regardless of which constructor is used (if you have more than one) or the parameters of your constructors (if they have arguments), although a constructor might subsequently change the value (if it is not final). So using an initializer with a declaration suggests to a reader that the initialized value is the value that the field has in all cases, regardless of which constructor is used and regardless of the parameters passed to any constructor. Therefore use an initializer with the declaration only if, and always if, the value for all constructed objects is the same.
There are many and various situations.
I just need an empty list
The situation is clear. I just need to prepare my list and prevent an exception from being thrown when someone adds an item to the list.
public class CsvFile
{
private List<CsvRow> lines = new List<CsvRow>();
public CsvFile()
{
}
}
I know the values
I exactly know what values I want to have by default or I need to use some other logic.
public class AdminTeam
{
private List<string> usernames;
public AdminTeam()
{
usernames = new List<string>() {"usernameA", "usernameB"};
}
}
or
public class AdminTeam
{
private List<string> usernames;
public AdminTeam()
{
usernames = GetDefaultUsers(2);
}
}
Empty list with possible values
Sometimes I expect an empty list by default with a possibility of adding values through another constructor.
public class AdminTeam
{
private List<string> usernames = new List<string>();
public AdminTeam()
{
}
public AdminTeam(List<string> admins)
{
admins.ForEach(x => usernames.Add(x));
}
}
What if I told you, it depends?
I in general initialize everything and do it in a consistent way. Yes it's overly explicit but it's also a little easier to maintain.
If we are worried about performance, well then I initialize only what has to be done and place it in the areas it gives the most bang for the buck.
In a real time system, I question if I even need the variable or constant at all.
And in C++ I often do next to no initialization in either place and move it into an Init() function. Why? Well, in C++ if you're initializing something that can throw an exception during object construction you open yourself to memory leaks.
The design of C# suggests that inline initialization is preferred, or it wouldn't be in the language. Any time you can avoid a cross-reference between different places in the code, you're generally better off.
There is also the matter of consistency with static field initialization, which needs to be inline for best performance. The Framework Design Guidelines for Constructor Design say this:
✓ CONSIDER initializing static fields inline rather than explicitly using static constructors, because the runtime is able to optimize the performance of types that don’t have an explicitly defined static constructor.
"Consider" in this context means to do so unless there's a good reason not to. In the case of static initializer fields, a good reason would be if initialization is too complex to be coded inline.
Being consistent is important, but this is the question to ask yourself:
"Do I have a constructor for anything else?"
Typically, I am creating models for data transfers that the class itself does nothing except work as housing for variables.
In these scenarios, I usually don't have any methods or constructors. It would feel silly to me to create a constructor for the exclusive purpose of initializing my lists, especially since I can initialize them in-line with the declaration.
So as many others have said, it depends on your usage. Keep it simple, and don't make anything extra that you don't have to.
Consider the situation where you have more than one constructor. Will the initialization be different for the different constructors? If they will be the same, then why repeat for each constructor? This is in line with kokos statement, but may not be related to parameters. Let's say, for example, you want to keep a flag which shows how the object was created. Then that flag would be initialized differently for different constructors regardless of the constructor parameters. On the other hand, if you repeat the same initialization for each constructor you leave the possibility that you (unintentionally) change the initialization parameter in some of the constructors but not in others. So, the basic concept here is that common code should have a common location and not be potentially repeated in different locations. So I would say always put it in the declaration until you have a specific situation where that no longer works for you.
There is a slight performance benefit to setting the value in the declaration. If you set it in the constructor it is actually being set twice (first to the default value, then reset in the ctor).
When you don't need some logic or error handling:
Initialize class fields at declaration
When you need some logic or error handling:
Initialize class fields in constructor
This works well when the initialization value is available and the
initialization can be put on one line. However, this form of
initialization has limitations because of its simplicity. If
initialization requires some logic (for example, error handling or a
for loop to fill a complex array), simple assignment is inadequate.
Instance variables can be initialized in constructors, where error
handling or other logic can be used.
From https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html .
I normally try the constructor to do nothing but getting the dependencies and initializing the related instance members with them. This will make you life easier if you want to unit test your classes.
If the value you are going to assign to an instance variable does not get influenced by any of the parameters you are going to pass to you constructor then assign it at declaration time.
Not a direct answer to your question about the best practice but an important and related refresher point is that in the case of a generic class definition, either leave it on compiler to initialize with default values or we have to use a special method to initialize fields to their default values (if that is absolute necessary for code readability).
class MyGeneric<T>
{
T data;
//T data = ""; // <-- ERROR
//T data = 0; // <-- ERROR
//T data = null; // <-- ERROR
public MyGeneric()
{
// All of the above errors would be errors here in constructor as well
}
}
And the special method to initialize a generic field to its default value is the following:
class MyGeneric<T>
{
T data = default(T);
public MyGeneric()
{
// The same method can be used here in constructor
}
}
"Prefer initialization in declaration", seems like a good general practice.
Here is an example which cannot be initialized in the declaration so it has to be done in the constructor.
"Error CS0236 A field initializer cannot reference the non-static field, method, or property"
class UserViewModel
{
// Cannot be set here
public ICommand UpdateCommad { get; private set; }
public UserViewModel()
{
UpdateCommad = new GenericCommand(Update_Method); // <== THIS WORKS
}
void Update_Method(object? parameter)
{
}
}

C# String gone from struct

Ok.. I have a really awkward problem that I believe is related with how C# handles value types vs reference types but I'm just not sure what exactly the bug is.
public partial class LogicSimulationViewerForm : Form
{
private Dictionary<string, PointStruct> pointValues;
private void SearchPoint(string code)
{
ReadDefaultPointValuesResponse result = ddcdao.ReadDefaultPoint(points);
pointValues = new Dictionary<string, PointStruct>();
for (int j = 0; j < result.pointidentifier.Length; j++)
{
if (!pointValues.ContainsKey(result.pointidentifier[j]))
{
PointStruct ps = new PointStruct();
ps.name = "Random String";
ps.pointidentifier = result.pointidentifier[j];
ps.outofservice = result.outofservice[j];
pointValues.Add(result.pointidentifier[j], ps);
...
pointValues is stored as a private field in a class. Now in the same class but in a different function, if I try to do the following:
PointStruct ps = pointValues[s];
MessageBox.Show(ps.name);
MessageBox.Show(ps.pointidentifier);
MessageBox.Show(ps.outofservice);
The ps.pointidentifier and ps.outofservice is displayed correctly but ps.name is always returned as null no matter what I do. How can I fix this issue?
Edit: Upon request, I am adding more code to further illustrate the problem:
public struct PointStruct
{
public string pointidentifier;
public string affect;
public string outofservice;
public string priorityarray;
public string pointtype;
public string alarmstate;
public string correctvalue;
public string presentvalue;
public string name;
public string test;
}
As long as there is no voodoo (explicit field layouts, property indirection, etc), there is absolutely no reason why a field should wipe itself, regardless of whether it is a class or a struct.
If it was a class, we could perhaps put that down to a careless update somewhere else, i.e.
var foo = pointValues[key];
// snip 2000 lines
foo.name = newValue; // which happens to be null
which would of course update the same fundamental object as the one referenced by the dictionary. But that doesn't apply to a struct, since the copies are separate (unless updating directly in an array).
The only way I can see of causing that, given that you state that pointValues.Add(...) is only used in one place, is that you are overwriting it elsewhere via the indexer:
pointValues[key] = newValueWithANullName;
All that said, though; unless you have some very specific reasons, there is very little purpose for PointStruct to be a struct. That looks to me like it should be a class. It is very "fat" for a struct. Also; in most cases, structs should be immutable.
It would be very surprising for a struct stored in a Dictionary to have any of its string fields change to hold anything other than the value they held when the struct was stored in the Dictionary. Is your name actually a literal "Random String", or are you using that literal to represent some other function? Have you confirmed that the function in question is actually working?
Unlike some people here, I very much like mutable structs, despite the limitations in .net's support for them, because they allow the owner of a struct to control who can mutate it. By contrast, if a reference to a mutable class object has ever been exposed to outside code, there's no telling when or by whom it might be altered. The fact that PointStruct is a struct means that there's a 99.44% chance that the field contents of the struct you are retrieving from the Dictionary are the same as the field contents the struct had when it was stored. Add a check to ensure that the Name field is non-null whenever it's stored to the Dictionary and you'll almost certainly find your problem. A much better situation to be in than with a mutable class, where you'd have to inspect outside code to ensure that nothing's altering it.
Addendum
There is one evil thing about mutable structs, which is that if you have any struct members, other than a constructor or property setters, which mutate this, an attempt to use such a member in read-only contexts will generate bogus code but won't generate any compiler diagnostics. Languages and frameworks which properly support value-type semantics require that members which mutate this be tagged as such, and forbid the use of such members in read-only contexts, but unfortunately .net has no such tagging. It simply guesses that constructors and property setters will mutate the underlying struct, while getters and other methods will not. If the `Name field is filled in with a struct method, e.g.
void ComputeName(void)
{
Name = someRandomString();
}
I would strongly suggest that you replace it with a static method:
void ComputeName(ref theStruct)
{
theStruct.Name = someRandomString();
}
If the former function is called on a read-only instance of PointStruct, the compiler will--as noted--compile without complaint but the resulting code won't work. Attempting to pass a read-only instance of PointStruct to the latter, however, will cause a compiler error.

In C#, what fires first, private member variables or constructors, and why?

If I have a class like:
public class A
{
public A(string name)
{
Console.WriteLine("Mon");
}
}
public class B
{
private A m_a = new A("Tues");
public B()
{
m_a = new A("Wed");
}
}
I'm not on a windows machine so I can't test the output.
What would it be, but more importantly why is it that way?
i.e why would the private var get instantiated before the constructor, or visa versa. Or would one be ignored or simply over-written?
Would Java be the same behaviour?
In both C# and Java all the initialization that is outside a constructor comes before any calls to the constructor. The assignment in the constructor would overwrite the other assignment.
For C# at least you can see the details of the language specification in section 10.11. That should answer any of the finer details of ordering, especially where inheritance is concerned.
I don't know how it works in Java (probably the same), but in C# member variables are instantiated before the constructor runs. As to why, I've never thought about it, and I don't know the best answer, but a pragmatic answer would be so that the member variables are available, already instantiated, in the constructor.
Variable initializers (within the class) are called before the constructor for that class. So private A m_a = new A("Tues") would be called before m_a = new A("Wed"), because the constructor might need to use the values of the private variables. I would assume Java does it the same way, but I can't test it right now.
As per the C# specification 17.4.5 Variable initializers:
For instance fields, variable
initializers correspond to assignment
statements that are executed when an
instance of the class is created.
All fields also have default value initializers that run regardless of whether the field has a variable initializer:
The default value initialization
described in 1.4.3 occurs for all
fields, including fields that have
variable initializers. Thus, when a
class is initialized, all static
fields in that class are first
initialized to their default values,
and then the static field initializers
are executed in textual order.
Likewise, when an instance of a class
is created, all instance fields in
that instance are first initialized to
their default values, and then the
instance field initializers are
executed in textual order.
So basically, there is no difference between private member initialization and construction initialization - the compiler will put it all the object's instance initialization routine, in textual order.

Why Must I Initialize All Fields in my C# struct with a Non-Default Constructor?

I would like to try this code:
public struct Direction
{
private int _azimuth;
public int Azimuth
{
get { return _azimuth; }
set { _azimuth = value; }
}
public Direction(int azimuth)
{
Azimuth = azimuth
}
}
But it fails on compilation, I understand that struct need to init all its fields.
but i am trying to understand what happens under the CLR\IL hoods.
why it need all the fields before any other method\property\this etc.
Thanks.
Value Types are created on the stack (unless nested within a reference type) There is something about fields/locations on the stack that the CLR can't guarantee that they will be zeroed out (contrary to fields/locations on the managed heap which are guaranteed to be zeroed out). Hence they must be written to before being read. Otherwise it's a security hole.
The struct's default ctor (which takes no parameters and which you're not allowed to explicitly specify) zeroes out all fields of a struct and hence you can use a struct after you do.
new BimonthlyPairStruct()
However when you implement your parameterized ctor, you must ensure that all fields have been initialized - which is required for the CLR to pass your code as safe/verified .
See Also: CLR via C# 2nd Ed - Pg 188
I just found an explanation in the MSDN forum stating that this rule is enforced because zeroing out the memory is skipped if you use a none default constructor. So you will have to provide initialization values for all fields in order to avoid some fields containing random values. You achieve this easily be calling the parameter less default constructor, but at the cost of initializing some fields twice.
I cannot tell if this explanation is correct, but it sounds reasonable.
When you define a non-default initializer, C# requires you to set all fields because it
skips the zeroing of memory and lets you initialize it - otherwise you'd have to have a
double initialization performance hit. If you don't care about the (very slight)
performance hit you can always chain a call to the : this() initializer and then only
initialize selected fields.
This is because structs are derived from System.ValueType and not System.Object, System.ValueType implements default constructur which you cannnot override, this default constructer initializes all fields in struct with its default value. So if you are implementing any parameter contructor in your class you will also need t0 ensure you invoke system.ValueType default const. And to answer why it needs to init all its value this is because value are stored in stack memory.
This works:
public Direction(int azimuth)
{
_azimuth = azimuth;
}
From the spec:
Struct constructors are invoked with
the new operator, but that does not
imply that memory is being allocated.
Instead of dynamically allocating an
object and returning a reference to
it, a struct constructor simply
returns the struct value itself
(typically in a temporary location on
the stack), and this value is then
copied as necessary.
Basically, the compiler must see that every field gets initialized in the constructor so that it can copy those values, and it is not willing to examine calls to functions or properties.
public struct Direction
{
public int Azimuth { get; private set; }
public Direction(int azimuth) : this()
{
Azimuth = azimuth;
}
}
You need to initialize the field, and not via the property.

Categories