Initializing null variables in .NET
Asked Answered
F

10

7

What is the proper way to initialize a null variable in .NET? I've been told by one of my colleagues that hard defining of a variable to null is a slowdown.

int var1;          // good practice
string s1;         // good practice

int var2 = 0;      // bad practice
string s2 = null;  // bad practice

Is that correct?

Falls answered 28/8, 2010 at 20:16 Comment(0)
P
9

Assuming you actually mean the default value instead of a null value, it could slow things down very, very slightly if you actually assign the value in the constructor instead of in the variable declaration. If it's part of the variable declaration I would probably expect the JIT compiler to remove the unnecessary assignment, as the object's memory is wiped on first initialization.

However, the chances of this being significant are absolutely tiny in either case.

Which do you find the more readable form? That's much more important in the vast majority of cases.

EDIT: Note that for static fields at least, there are subtle cases where the two don't behave the same way. Here's an example - the Test1 and Test2 classes differ only in terms of whether the y declaration has an assignment:

using System;

class Test1
{
    static int x = GetX();
    static int y = 0;

    public static void Hello()
    {
        Console.WriteLine("{0} {1}", x, y);
    }

    static int GetX()
    {
        y = 2;
        return 5;
    }
}

class Test2
{
    static int x = GetX();
    static int y;

    public static void Hello()
    {
        Console.WriteLine("{0} {1}", x, y);
    }

    static int GetX()
    {
        y = 2;
        return 5;
    }
}

class Test
{
    static void Main()
    {
        Test1.Hello();
        Test2.Hello(); 
    }
}
Platte answered 28/8, 2010 at 20:21 Comment(6)
Isn't the compiler smart enough to generate the same IL for both declarations?Perzan
@sztomi: The C# compiler doesn't. Whether the JIT compiler does is a different matter.Platte
bcoz, The default value of an integral type is equivalent to the literal 0. (via MSDN)Pollinize
@Ankit: Yes, I know it's the default value. But there are subtle cases where it may actually make a difference, at least for static fields.Platte
NOT working for all variables: int? P6_01, P6_02, P6_03, P6_04, P6_10_1 = null;Murk
@Kiquenet: Your comment is unclear. What's "not working" about that? What does it do vs what you expect it to do? I suspect this may be better asked as a new question with appropriate detail.Platte
M
3

For an int in .net, it's actually not possible to assign null to it as it's a value type, rather than a reference type, unless you create it as an int? (Nullable<int>), which whilst it is a value type, has special semantics and can thus have null assigned to it.

In your example, there's no point assigning 0 to var2 as the default value for an int is zero. That said, I'd be quite surprised if the c# compiler (although it may be the case tha tthe compiler produces different MSIL for the two) / CLR interpreter treats both as being exactly the same.

private void MyFunction()
{
    int i;
    string s;

    if (s == "3")
    {
        if (i == 1)
        {
        }
    }
}

Bear in mind that in this, ultimately pointless, function, you'd get a compilation error for both the attempt to compare s and i as both are "unassigned locals". This is different from member variables of a class, like:

public class MyClass
{
    int i;

    public void MyFunction()
    {
        if (i == 1)
        {
        }
    }
}
Mirandamire answered 28/8, 2010 at 20:18 Comment(1)
@0xA3, that'll teach me to try using my brain after a glass and a half of wine! =)Mirandamire
I
2

You cannot assign null to a value type such as int. However, in later versions of .NET, you can use nullable value types:

int? var1 = null;

It is not a bad practice to initialize variables in their declarations. In fact, it's quite the opposite. By doing so, there's no question in anyone's mind about the value of the variable after it's declared.

Also, there's such a minimal performance penalty for assigning null to a variable that you needn't worry about it. Focus on programming for accurate functionality before anything else; once you have that, then adjust for any glaring performance issues that may arise.

Indulgent answered 28/8, 2010 at 20:24 Comment(0)
C
1

I wouldn't say the latter is a bad practice. It's more explicit and a well-known idiom amongst programmers of C-style languages.

Cattleya answered 28/8, 2010 at 20:21 Comment(1)
+1, but I wouldn't really associate C with C# (a silly thing to do, honestly). That said, I guess the culture might carry over a bit, but since the languages are so different (For example, in C, there are no default values)...Cornered
J
1

An integer is a value type, so it can't be initialized to null.

The performance loss for pre-initialization is arguably negligible, but if it isn't necessary, it should be avoided. For details, check out how to gain performance by not initializing variables. Also, check out Jeff Atwood's blog post: For Best Results, Don't Initialize Variables.

Jerry answered 28/8, 2010 at 20:21 Comment(0)
P
1

Any uninitialized use of a variable in C# will generate a compiler warning (if there is at least one code path the do not initializes). And there should not be any warnings in your final code!

In the second statement you are specifying a default value. In the first statement you have assumed that all code-paths will assign some value to it.

Pollinize answered 28/8, 2010 at 20:22 Comment(0)
C
1

You'll want to initialize local variables of reference type to null if there is no other explicit value assigned, or you will run into "uninitialized local variable" compile errors. Example:

Err

// Inside a method, property or indexer.
Random r; // compile error - Uninitialized local var

The same goes for other kinds of local variables, both reference and value type. In your example it uses a value type and the local variable should be declared:

int var1 = 0;

The same good form for reference types is:

// Inside a method, property or indexer.
Random r = null;

On the other hand Fields e.g. "member variables" are at the class level you don't need to assign an explicit value to these.

See also:

Clairclairaudience answered 28/8, 2010 at 20:24 Comment(0)
A
1

If you are talking about member variables, there is maybe another reason to not initialize them with their default values: the FxCop compliance to the rule CA1805: DoNotInitializeUnnecessarily.

If one of the requirements is to write FxCop compliant code, you cannot initialize variables with default values.

Algonquian answered 28/8, 2010 at 20:26 Comment(2)
Maybe you wanted to differentiate between local variables and member variables (fields)?Trilobite
@Ben Voigt: answer modified. Thanks to note the difference.Algonquian
T
1

The CLR makes a hard promise that all local variables will be initialized to their default value upon entry into the method before the first statement is executed. This promise is implemented by the JIT compiler. Seeing this is a bit difficult since the C# requires variables to be initialized explicitly before they are used. But here's an example:

    static void Main(string[] args) {
        int ix;
        int.TryParse("42", out ix);
        Console.WriteLine("", ix);
    }

Use Debug + Windows + Disassembly to see the generated code:

// Stack frame setup elided...
00000006  xor         eax,eax                        ; eax = 0
00000008  mov         dword ptr [ebp-0Ch],eax        ; ix = 0
// etc..

Rewriting this to initialize ix to zero produces this code:

00000006  xor         eax,eax                        ; eax = 0
00000008  mov         dword ptr [ebp-0Ch],eax        ; ix = 0
0000000b  xor         edx,edx                        ; edx = 0
0000000d  mov         dword ptr [ebp-0Ch],edx        ; ix = 0

Well, that's a bit sad. The JIT compiler is usually quite good at optimizing useless code away but fumbles in this particular case.

So, you're friend is right. At least for the x86 JIT compiler, not close to an x64 machine right now. The overhead is probably around half a nanosecond or so. Not something that is easy to measure.

Trinette answered 28/8, 2010 at 21:0 Comment(0)
N
0

While this is an old question from OP, Visual Studio 2022 (v17) enables the Nullable setting for C# .NET 6 LTS Class Library projects:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

This creates is a new context for searching out this question. Especially when considering the assignment of the !(null-forgiving) operator to a variable or field.

tl;dr - There is no runtime performance impact when assigning a !(null-forgiving) operator to a variable or field with Nullable enabled.

According to Microsoft document on Nullable reference types,

Nullable reference types aren't new class types, but rather annotations on existing reference types. The compiler uses those annotations to help you find potential null reference errors in your code. There's no runtime difference between a non-nullable reference type and a nullable reference type. The compiler doesn't add any runtime checking for non-nullable reference types. The benefits are in the compile-time analysis. The compiler generates warnings that help you find and fix potential null errors in your code. You declare your intent, and the compiler warns you when your code violates that intent.

Novelette answered 10/1, 2022 at 12:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.