What does .Net do when you declare an object without an instance? - c#

I wonder to know how the .Net Framework handles the declared but not instantiated object situation.
For example i declare an object like
DropDownList ddl;
and do nothing about it. I know that i should do something with this variable and get a warning about it, but what i don't know is the where it will be stored.
Is there a lookup table that stores the data of all declared variables? Or is there a virtual reference for every declaration?
Edit : I just wanted to know how the memory allocated for this object declaration.
Edit2 : Whether it's a local variable or not, i'm just talking about the memory allocation structure. I wonder to know where this references stored.

If ddl is a field, then the value of ddl will be null, as it is a reference type.
Any attempt to call a member on it will result in a NullReferenceException.
If it is a local variable it will simply be unassigned.
Value types will get the default(T) of their type.
The compiler itself may remove the call completely, depending on where it was declared, but this is an implementation detail.

If you are talking about a local variable then the compiler can simply optimize it out of existence since noone can be using it (if you attempted to use it without initializing the compiler would have protested with an error). In fact the .NET 4 compiler did this for me when I tested just moments ago.
If you are talking about a field in a class then it is initialized with the default value for its type as part of the object construction.

From your description, it sounds like you're talking about a local variable. When you declare a local variable in usual implementations and without any optimizations, then space is reserved for it on the stack (most probably), with a null reference as its value.
You could look into the StackFrame class if you want to inspect further (I've never used it).

The variable is stored in your assembly. It will always have it's default value null.
In release mode (compiler is set to optimize) it's optimized and it is not stored anywhere.
If you want to know more about IL and how the compiler works, wikipedia has a good article to start.

All variables are stored into a class or method. Variables declared into a class can be listed using .NET Reflection :
class Class1 { private int i; public string s; }
typeof(Class1).GetFields(BindingFlags.Instance); // returns all instance fields
typeof(Class1).GetFields(); // returns all instance public fields
typeof(Class1).GetProperties(); // returns all instance public properties
Variables declared into a method cannot be inspected with .NET Reflection mechanisms.

Related

why we cannot initialize an instance field at declaration in c# struct?

In c# -> struct, we cannot assign a value to instance field at declaration. Can you tell me the reason? Thanks.
A simple example:
struct Test
{
public int age =10; // it's not allowed.
}
I think the answer is very simple, but hard to get a grasp of if you do not know the difference between value types and reference types.
Maybe something to note is that reference type are held in the heap, which the garbage collect cleans. And a value type lives in the stack. Every time you define a scope, like:
{
}
A new local stack is created. Once you exit this scope, all value types on the stack are disposed unless a reference is held to them on the heap.
Seeing as reference types and value types are very differently handled, they are also designed with these changes in mind. Not being able to have empty constructors and also not being able to assign values on construction is a logical result of this.
I found a very old stackoverflow question regarding the same, they also have some short answers regarding it being designed like that for performance reasons:
Why can't I initialize my fields in my structs?
My source for this info was the ref book for 70-483.
Hope this gave you the clarification you are looking for

What the purpose of this = default(...) in struct constructor?

During an research the purpose of this reassignment possibility with structs I ran into following puzzle: Why it is needed to do this = default(...) at the beginning of some struct constructor. It's actually zeroes already zeroed memory, isn't it?
See an example from .NET core:
public CancellationToken(bool canceled)
{
this = default(CancellationToken);
if (canceled)
{
this.m_source = CancellationTokenSource.InternalGetStaticSource(canceled);
}
}
It's actually zeroes already zeroed memory, isn't it?
No. When you create custom constructor for struct, it's your responsibility to set each and every field of struct to some value.
Just default .ctor() will fill it with zeroes - and that's one of the reasons why you are not allowed to implement own default .ctor for struct in C# (while CLR technically allows it, but it's a different topic to discuss).
So technique here is to call default(), which will create separate instance filled with zeroes, when using 'this = ' assignment will copy all fields from right to left (as it is struct), which will satisfy you need to initialize every field of struct. Then, you can do whatever you want.
In most cases it might be better (from code readability) to use something like this instead:
public MyStruct(..) : this() {
...
}
It's meeting a requirement for struct constructors:
If the struct instance constructor doesn’t specify a constructor initializer, the this variable corresponds to an out parameter of the struct type, and similar to an out parameter, this must be definitely assigned (§5.3) at every location where the constructor returns
C# Language Spec, Version 5, section 11.3.8
Of course, it doesn't have to be default() - it could be anything. But this must be assigned.
The rules for definite assignment (from section 5.3 referenced above) say, in part:
The definite assignment states of instance variables of a struct-type variable are tracked individually as well as collectively. In additional to the rules above, the following rules apply to struct-type variables and their instance variables:
An instance variable is considered definitely assigned if its containing struct-type variable is considered definitely assigned.
A struct-type variable is considered definitely assigned if each of its instance variables is considered definitely assigned.

Why anonymous methods inside structs can not access instance members of 'this'

I have a code like the following:
struct A
{
void SomeMethod()
{
var items = Enumerable.Range(0, 10).Where(i => i == _field);
}
int _field;
}
... and then i get the following compiler error:
Anonymous methods inside structs can not access instance members of 'this'.
Can anybody explains what's going on here.
Variables are captured by reference (even if they were actually value-types; boxing is done then).
However, this in a ValueType (struct) cannot be boxed, and hence you cannot capture it.
Eric Lippert has a nice article on the surprises of capturing ValueTypes. Let me find the link
The Truth About Value Types
Note in response to the comment by Chris Sinclair:
As a quick fix, you can store the struct in a local variable: A thisA = this; var items = Enumerable.Range(0, 10).Where(i => i == thisA._field); – Chris Sinclair 4 mins ago
Beware of the fact that this creates surprising situations: the identity of thisA is not the same as this. More explicitly, if you choose to keep the lambda around longer, it will have the boxed copy thisA captured by reference, and not the actual instance that SomeMethod was called on.
When you have an anonymous method it will be compiled into a new class, that class will have one method (the one you define). It will also have a reference to each variable that you used that was outside of the scope of the anonymous method. It's important to emphasize that it is a reference, not a copy, of that variable. "lambdas close over variables, not values" as the saying goes. This means that if you close over a variable outside of the scope of a lambda, and then change that variable after defining the anonymous method (but before invoking it) then you will see the changed value when you do invoke it).
So, what's the point of all of that. Well, if you were to close over this for a struct, which is a value type, it's possible for the lambda to outlive the struct. The anonymous method will be in a class, not a struct, so it will go on the heap, live as long as it needs to, and you are free to pass a reference to that class (directly or indirectly) wherever you want.
Now imagine that we have a local variable, with a struct of the type you've defined here. We use this named method to generate a lambda, and let's assume for a moment that the query items is returned (instead of the method being void). Would could then store that query in another instance (instead of local) variable, and iterate over that query some time later on another method. What would happen here? In essence, we would have held onto a reference to a value type that was on the stack once it is no longer in scope.
What does that mean? The answer is, we have no idea. (Please look over the link; it's kinda the crux of my argument.) The data could just happen to be the same, it could have been zeroed out, it could have been filled by entirely different objects, there is no way of knowing. C# goes to great lengths, as a language, to prevent you from doing things like this. Languages such as C or C++ don't try so hard to stop you from shooting your own foot.
Now, in this particular case, it's possible that you aren't going to use the lambda outside of the scope of what this refers to, but the compiler doesn't know that, and if it lets you create the lambda it has no way of determining whether or not you expose it in a way that could result in it outliving this, so the only way to prevent this problem is to disallow some cases that aren't actually problematic.

Why are static fields null by default?

Just curious, from the code below I can see that static field of type A will be null by default while variable of that type needs to be initialized to ahve at least null value. Could anyone explain the difference a bit more? Thanks
class Program
{
static A _a; //it is null by default
static void Main(string[] args)
{
A nonStaticA; //empty reference, exception when used
A correctA=null;
}
}
class A
{
}
The initial value of a field, whether it be a static field or an instance field, is the default value of the field's type. It is not possible to observe the value of a field before this default initialization has occurred, and a field is thus never "uninitialized".
If a static constructor exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.
A local variable is not automatically initialized and thus has no default value. For the purpose of definite assignment checking, a local variable is considered initially unassigned.
The difference is between local variables and fields, not between static and instance.
Local variables of any type are required to be initialized to a value before they are used the first time. This prevents bugs where you forget to initialize a variable.
The compiler can verify this, because local variables only exist inside a single method, and code in a method is executed in a predictable order, from the top town. So it is easy to check if a variable is accessed before it is initialized.
Fields are different. They can be accessed in multiple methods, and there is no way the compiler can determine in which order they are executed. Therefore it cannot check at compile-time that fields are initialized before they are accessed. Instead fields are given a default value, which is null for all reference types, 0 for integers and so on.
It has nothing to do with static. Class fields (instance and static) are initialized to their defaults, local variables are not.
And why? Like lots of things it was a design decision at some point.
C#, as far as I can observes, kept many things as they were in other previous languages, mainly C++.
The reason in C++ (which may or may not be relevant to C#) is that static (or global) objects are statically written into the executable or library while for other objects the code that creates the object (and not the object itself) is written into the executable or library. For objects on the stack usually code that subtracts some value from the stack pointer is written.
When the executable or library is loaded into memory by the OS the static fields are just a bunch of bytes that are copied as is into memory (the data segment of the process). Since they are copied as is, they already have a value (the value in the executable or library file). Because of that there is no performance implications to setting it to a specific value. For that reason (as far as I can see) the C++ standard made their value deterministic (if they are not initialized explicitly) and what is more natural than zero as an initialization value?!
In order to initialize a dynamic object (whether it is on the stack or the heap) code has to be inserted into the executable or library. This has performance implications (and maybe other implications) so the C++ standard preferred to leave it up to the programmer.
I'm not completely sure every bit of this data is true, but it is what seems logical to me from what I know.

Unassigned value error in C#

if variable is not assigned, then it takes the default value at run time.
for example
int A1;
if i will check the value of A1 at runtime it will be 0;
then why at compile time it throws a error of unassigned value;
why CLR don't use to a lot the default value at runtime;
int A1;
int B1 = A1+10;
it should be 11 as the default value of A1 is 0;
there project property where i can check for "assign default values for unassigned variable";
Can anybody tell me where i can find it?
Your statement
if variable is not assigned,then it takes the default value at run time
is only true for member variables in a class.
For local variables inside a function, this is wrong. Local variables inside a function always require initialization.
it should be 11 as the default value of A1 is 0;
This is exactly the reason that the C# compiler won't let you get away with using uninitialized variables. The result would be 10, not 11. After a good 30 years of experience with C and C++, languages that allow you to use uninitialized variables, the C# team decided that this was a major source of bugs and to not allow this in a C# program.
There are lots of little tweaks like this. Another great example is not allowing fall through to another case in a switch statement. Forgetting to write break is such a classic bug. Outlawing these C-isms is rather an excellent idea and a big part of why C# is such a great language. Unless you dislike the idea of a compiler as a police officer.
Fwiw: using an uninitialized variable is permitted in VB.NET.
Default value is true for class members, but not for function locals. Whatever code you put directly into an as[pc]x file, the code generator will put it into a function.
Most of the time this happens is because the variable is an Object and before you can use it you need to Instantiate it.
When you assign a String = "" this is instantiated for you
You are talking about local variables or class level variables ? The rules are different for both. Check our Jon Skeet's reply at this:
Initialization of instance fields vs. local variables
The heap (reference classes) and the constructor for structs zero's the data.
Simple value-types like int, but also references (=pointers) to objects, do not get a default value on the stack. You should always set it. If this was not mandatory, specially with object-pointers, this could be a major security breach, because you are pointing to unknown locations.
Any default value (like 0) would probably be wrong 50% of the time.

Categories

Resources