开发者

Initializing null variables in .NET

开发者 https://www.devze.com 2023-01-13 06:22 出处:网络
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.

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?


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(); 
    }
}


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)
        {
        }
    }
}


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.


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.


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.


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:

  • What is the difference between a member variable and a local variable?
  • C# Concepts: Value vs Reference Types


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.


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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消