I instantiate an array like this:
int array[] = new int[4];
What are the default values for those four members? Is it null, 0 or not exists?
It's 0. It can't be null, as null isn't a valid int value.
From section 7.6.10.4 of the C# 5 specification:
All elements of the new array instance are initialized to their default values (§5.2).
And from section 5.2:
The default value of a variable depends on the type of the variable and is determined as follows:
For a variable of a value-type, the default value is the same as the value computed by the value-type’s default constructor (§4.1.2).
For a variable of a reference-type, the default value is null.
Initialization to default values is typically done by having the memory manager or garbage collector initialize memory to all-bits-zero before it is allocated for use. For this reason, it is convenient to use all-bits-zero to represent the null reference.
(As an implementation detail, there's some trickiness around the first bullet point. Although C# itself doesn't allow you to declare a parameterless constructor for value types, you can create your own parameterless constructors for value types in IL. I don't believe those constructors are called in array initialization, but they will be called in a new X() expression in C#. It's outside the realm of the C# spec though, really.)
The default value of an automatically-initialized variable of type T, such as an array element or an instance field, is the same as the value of default(T). For reference types and pointer types, it's null. For numeric types, it is the zero of that type. For bool, it's false. For struct types, it is the struct value that has all its fields initialized to their default values.
From Arrays (C# Programming Guide):
The default values of numeric array elements are set to zero, and reference elements are set to null.
Integers cannot be NULL. They will have the value '0'. Even if you try to assign NULL to an int from code, you will not be able to do it.
Related
In c# using .Net, if you create a class with an uninitialized field and without a constructor, then create an instance of the class with the new keyword, .Net sets the value of the field to the "default value". What exactly does that mean? Is there ever a situation where the value would be set to Null?
Like Johnny mentioned in the comments, this table lists the default values for .NET types. The default value of a reference-type field is null.
The default value is defined on a per-type basis. In general, any reference type will default to null.
You can find a full list of default values based on the type in the documentation.
Furthermore, you can find out empirically by explicitly using the default keyword and checking (e.g. in the debugger) what value was returned:
var x = default(string);
var y = default(int);
I have a sequence of structs like so:
struct Foo { }
...
// somewhere else
var foos = GetListOfFoos();
...
// somewhere else
var foo = foos.FirstOrDefault();
Now, should I just go ahead and use the foo I just retrieved without worrying about nullability, of course because structs are not nullable since they're value types.
It just feels a bit worrying.
I know this is a stupid question and the answer is, "Yes, just use it without any checks for null." But I don't know why I am asking this even or what the question here is.
I am not missing anything by not checking for nullability here, right? There cannot be an invalid state for structs put inside that IEnumerable<T>, right?
Of course, I understand that if Foo had uninitialized members because it declared a parameterized ctor that did not initialize each and every member, one or more members of the instance of Foo will be in an unsable state. But as such each instance of Foo in that list will amount to something and there's no need to check for nulls or anything as there is no such thing as default(Foo), right? Of course, just confirming.
Even if value types are not null you should worry about this value being the default value if that was exceptional or not expected.
there is no such thing as default(Foo)
Sure, It will return an instance of this type where all members are nitialized to their default alues.
If you take f.e. struct Guid then default(Guid) returns an instance which is equal to Guid.Empty or new Guid().
So my advice is, don't compare with default(yourStruct) because that could lead to nasty bugs if the default struct could be a valid instance. Instead you could use Any:
bool containsAny = foos.Any();
if(containsAny)
{
Foo firstFoo = foos.First();
}
MSDN: default
returns null for reference types(class types and interface types)
zero for numeric value types
for user-defined structs, it returns the struct initialized to the zero bit pattern, which produces 0 or null for each member depending on whether that member is a value or reference type. For nullable value types, default returns a System.Nullable<T>, which is initialized like any struct.
If T is a struct, you can't check for null: it will never be null, and a real "zero" (equivalent) in the list/sequence will be indistinguishable from "no there weren't any values in the list/sequence".
No, you don't need to check for null here.
I'm familiar with the C# specification, section 5.3 which says that a variable has to be assigned before use.
In C and unmanaged C++ this makes sense as the stack isn't cleared and the memory location used for a pointer could be anywhere (leading to a hard-to-track-down bug).
But I am under the impression that there are not truly "unassigned" values allowed by the runtime. In particular that a reference type that is not initialized will always have a null value, never the value left over from a previous invocation of the method or random value.
Is this correct, or have I been mistakenly assuming that a check for null is sufficient all these years? Can you have truly unintialized variables in C#, or does the CLR take care of this and there's always some value set?
I am under the impression that there are not truly "unassigned" values allowed by the runtime. In particular that a reference type that is not initialized will always have a null value, never the value left over from a previous invocation of the method or random value. Is this correct?
I note that no one has actually answered your question yet.
The answer to the question you actually asked is "sorta".
As others have noted, some variables (array elements, fields, and so on) are classified as being automatically "initially assigned" to their default value (which is null for reference types, zero for numeric types, false for bools, and the natural recursion for user-defined structs).
Some variables are not classified as initially assigned; local variables in particular are not initially assigned. They must be classified by the compiler as "definitely assigned" at all points where their values are used.
Your question then is actually "is a local variable that is classified as not definitely assigned actually initially assigned the same way that a field would be?" And the answer to that question is yes, in practice, the runtime initially assigns all locals.
This has several nice properties. First, you can observe them in the debugger to be in their default state before their first assignment. Second, there is no chance that the garbage collector will be tricked into dereferencing a bad pointer just because there was garbage left on the stack that is now being treated as a managed reference. And so on.
The runtime is permitted to leave the initial state of locals as whatever garbage happened to be there if it can do so safely. But as an implementation detail, it does not ever choose to do so. It zeros out the memory for a local variable aggressively.
The reason then for the rule that locals must be definitely assigned before they are used is not to prevent you from observing the garbage uninitialized state of the local. That is already unobservable because the CLR aggressively clears locals to their default values, the same as it does for fields and array elements. The reason this is illegal in C# is because using an unassigned local has high likelihood of being a bug. We simply make it illegal, and then the compiler prevents you from ever having such a bug.
As far as I'm aware, every type has a designated default value.
As per this document, fields of classes are assigned the default value.
http://msdn.microsoft.com/en-us/library/aa645756(v=vs.71).aspx
This document says that the following always have default values assigned automatically.
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.
http://msdn.microsoft.com/en-us/library/aa691173(v=vs.71).aspx
More information on the actual default values here:
Default values of C# types (C# reference)
It depends on where the variable is declared. Variables declared within a class are automatically initialized using the default value.
object o;
void Method()
{
if (o == null)
{
// This will execute
}
}
Variables declared within a method are not initialized, but when the variable is first used the compiler checks to make sure that it was initialized, so the code will not compile.
void Method()
{
object o;
if (o == null) // Compile error on this line
{
}
}
In particular that a reference type that is not initialized will always have a null value
I think you are mixing up local variables and member variables. Section 5.3 talks specifically about local variables. Unlike member variables that do get defaulted, local variables never default to the null value or anything else: they simply must be assigned before they are first read. Section 5.3 explains the rules that the compiler uses to determine if a local variable has been assigned or not.
There are 3 ways that a variable can be assigned an initial value:
By default -- this happens (for example) if you declare a class variable without assigning an initial value, so the initial value gets default(type) where type is whatever type you declare the variable to be.
With an initializer -- this happens when you declare a variable with an initial value, as in int i = 12;
Any point before its value is retrieved -- this happens (for example) if you have a local variable with no initial value. The compiler ensures that you have no reachable code paths that will read the value of the variable before it is assigned.
At no point will the compiler allow you to read the value of a variable that hasn't been initialized, so you never have to worry about what would happen if you tried.
All primitive data types have default values, so there isn't any need to worry about them.
All reference types are initialized to null values, so if you leave your reference types uninitialized and then call some method or property on that null ref type, you would get a runtime exception which would need to be handled gracefully.
Again, all Nullable types need to be checked for null or default value if they are not initialized as follows:
int? num = null;
if (num.HasValue == true)
{
System.Console.WriteLine("num = " + num.Value);
}
else
{
System.Console.WriteLine("num = Null");
}
//y is set to zero
int y = num.GetValueOrDefault();
// num.Value throws an InvalidOperationException if num.HasValue is false
try
{
y = num.Value;
}
catch (System.InvalidOperationException e)
{
System.Console.WriteLine(e.Message);
}
But, you will not get any compile error if you leave all your variables uninitialized as the compiler won't complain. It's only the run-time you need to worry about.
I have a class named A. What the difference between these two statements?
A a = new A();
A a = default(A);
This creates a new instance of the type A by calling the default, parameterless constructor:
A a = new A();
This assigns the default value for type A to the variable a and does not call any constructor at all:
A a = default(A);
The main difference is that the default value of a type is null for reference types and a zero-bit value for all value types (so default(int) would be 0, default(bool) would be false, etc.).
For value types there is no difference, since the default constructor of a value type is always equivalent to default(T). It just fills everything with 0, null, 0.0... In the default implementation of .net this just corresponds to filling everything in your variable with binary zero.
For reference types new T() calls the default constructor and returns a (usually) non null reference.
default(T) on the other hand is equivalent to null in this case.
default(T) is important because it represents a valid value of T, regardless whether T is a reference- or value-type. This is very useful in generic programming.
For example in functions like FirstOrDefault you need a valid value for your result in the case where the enumerable has no entries. And you just use default(T) for that since it's the only thing valid for every type.
Additionally calling the the default constructor on reference-types requires a generic constraint. And not every reference-type implements a default constructor. So you can't always use it.
The new keyword always signals memory allocation for reference types. No other construct actually creates space in memory for the data you are about to create. For value types, their memory is always pre-allocated when used in a function or procedure. The default keyword allows a generic type to return its default (uninitiazed) value, or null for reference types.
Just curious.
If you go:
string myString;
Its value is null.
But if you go:
int myInt;
What is the value of this variable in C#?
Thanks
David
Firstly, note that this is only applicable for fields, not local variables - those can't be read until they've been assigned, at least within C#. In fact the CLR initializes stack frames to 0 if you have an appropriate flag set - which I believe it is by default. It's rarely observable though - you have to go through some grotty hacks.
The default value of int is 0 - and for any type, it's essentially the value represented by a bit pattern full of zeroes. For a value type this is the equivalent of calling the parameterless constructor, and for a reference type this is null.
Basically the CLR wipes the memory clean with zeroes.
This is also the value given by default(SomeType) for any type.
default of int is 0
The default value for int is 0.
See here for the full list of default values per type: http://msdn.microsoft.com/en-us/library/83fhsxwc.aspx
Here is a table of default values for value types in C#:
http://msdn.microsoft.com/en-us/library/83fhsxwc.aspx
Reference types default value is usually null.
String is a reference type. Int is a value type. Reference types are simply a pointer on the stack directed at the heap, which may or may not contain a value. A value type is just the value on the stack, but it must always be set to something.
The value for an unitialized variable of type T is always default(T). For all reference types this is null, and for the value types see the link that #Blorgbeard posted (or write some code to check it).