Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does FxCop think initializing fields to the default value is bad?

Tags:

fxcop

When assigning a default default-value to a field (here false to a bool), FxCop says:

Resolution   : "'Bar.Bar()' initializes field 'Bar.foo' 
               of type 'bool' to false. Remove this initialization 
               because it will be done automatically by the runtime."

Now, I know that code as int a = 0 or bool ok = false is introducing some redundancy, but to me it seems a very, very good code-practice, one that my teachers insisted on righteously in my opinion.

Not only is the performance penalty very little, more importantly: relying on the default is relying on the knowledge of each programmer ever to use a piece of code, on every datatype that comes with a default. (DateTime?)

Seriously, I think this is very strange: the very program that should protect you from making all too obvious mistakes, is suggesting here to make one, only for some increased performance? (we're talking about initialization code here, only executed once! Programmers who care that much, can of course omit the initialization (and should probably use C or assembler :-) ).

Is FxCop making an obvious mistake here, or is there more to it?

Two updates :

  1. This is not just my opinion, but what I have been taught at university (Belgium). Not that I like to use an argumentum ad verecundiam, but just to show that it isn't just my opinion. And concerning that:

  2. My apologies, I just found this one:

    Should I always/ever/never initialize object fields to default values?

like image 378
Peter Avatar asked Apr 08 '09 17:04

Peter


5 Answers

There can be significant performance benefits from this, in some cases. For details, see this CodeProject article.

The main issue is that it is unnecessary in C#. In C++, things are different, so many professors teach that you should always initialize. The way the objects are initialized has changed in .NET.

In .NET, objects are always initialized when constructed. If you add an initializer, it's possible (typical) that you cause a double initialization of your variables. This happens whether you initialize them in the constructor or inline.

In addition, since initialization is unnecessary in .NET (it always happens, even if you don't explicitly say to initialize to the default), adding an initializer suggests, from a readability standpoint, that you are trying to add code that has a function. Every piece of code should have a purpose, or be removed if unnecessary. The "extra" code, even if it was harmless, suggests that it is there for a reason, which reduces maintainability.

like image 141
Reed Copsey Avatar answered Nov 18 '22 21:11

Reed Copsey


Reed Copsey said specifying default values for fields impacts performance, and he refers to a test from 2005.

public class A
{
    // Use CLR's default value
    private int varA;
    private string varB;
    private DataSet varC;
}

public class B
{
    // Specify default value explicitly
    private int varA = 0;
    private string varB = null;
    private DataSet varC = null;
}

Now eight years and four versions of C# and .NET later I decided to repeat that test under .NET Framework 4.5 and C# 5, compiled as Release with default optimizations using Visual Studio 2012. I was surprised to see that there is still a performance difference between explicitly initializing fields with their default values and not specifying a default value. I would have expected the later C# compilers to optimize those constant assignments away by now.

No init: 512,75    Init on Def: 536,96    Init in Const: 720,50
Method No init: 140,11    Method Init on Def: 166,86

(the rest)

So I peeked inside the constructors of classes A and B in this test, and both are empty:

.method public hidebysig specialname rtspecialname 
    instance void .ctor () cil managed 
{
    // Code size 7 (0x7)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: call instance void [mscorlib]System.Object::.ctor()
    IL_0006: ret
} // end of method .ctor

I could not find a reason in the IL why explicitly assigning default constant values to fields would consume more time. Apparently the C# compiler does optimize the constants away, and I suspect it always did.

So, then the test must be wrong... I swapped the contents of classes A and B, swapped the numbers in the result string, and reran the tests. And lo and behold now suddenly specifying default values is faster.

No init: 474,75    Init on Def: 464,42    Init in Const: 715,49
Method No init: 141,60    Method Init on Def: 171,78

(the rest)

Therefore I conclude that the C# compiler correctly optimizes for the case where you assign default values to fields. It makes no performance difference!


Now we know performance is really not an issue. And I disagree with Reed Copsey's statement "The 'extra' code, even if it was harmless, suggests that it is there for a reason, which reduces maintainability." and agree with Anders Hansson on this:

Think long term maintenance.

  • Keep the code as explicit as possible.
  • Don't rely on language specific ways to initialize if you don't have to. Maybe a newer version of the language will work differently?
  • Future programmers will thank you.
  • Management will thank you.
  • Why obfuscate things even the slightest?

Future maintainers may come from a different background. It really isn't about what is "right" it is more what will be easiest in the long run.

like image 6
Daniel A.A. Pelsmaeker Avatar answered Nov 18 '22 22:11

Daniel A.A. Pelsmaeker


FxCop has to provide rules for everyone, so if this rule doesn't appeal to you, just exclude it.

Now, I would suggest that if you want to explicitly declare a default value, use a constant (or static readonly variable) to do it. It will be even clearer than initializing with a value, and FXCop won't complain.

private const int DEFAULT_AGE = 0;

private int age = 0; // FXCop complains
private int age = DEFAULT_AGE; // FXCop is happy

private static readonly DateTime DEFAULT_BIRTH_DATE = default(DateTime);

private DateTime birthDate = default(DateTime); // FXCop doesn't complain, but it isn't as readable as below
private DateTime birthDate = DEFAULT_BIRTH_DATE; // Everyone's happy
like image 5
Michael Meadows Avatar answered Nov 18 '22 21:11

Michael Meadows


FX Cop sees it as adding unnecessary code and unnecessary code is bad. I agree with you, I like to see what it's set to, I think it makes it easier to read.

A similar problem we encounter is, for documentation reasons we may create an empty constructor like this

/// <summary>
/// a test class
/// </summary>
/// <remarks>Documented on 4/8/2009  by richard</remarks>
public class TestClass
{
    /// <summary>
    /// Initializes a new instance of the <see cref="TestClass"/> class.
    /// </summary>
    /// <remarks>Documented on 4/8/2009  by Bob</remarks>
    public TestClass()
    {
        //empty constructor
    }        
}

The compiler creates this constructor automatically, so FX cop complains but our sandcastle documentation rules require all public methods to be documented, so we just told fx cop not to complain about it.

like image 4
Bob The Janitor Avatar answered Nov 18 '22 21:11

Bob The Janitor


It's relies not on every programmer knowing some locally defined "corporate standard" which might change between at any time, but on something formally defined in the Standard. You might as well say "don't using x++ because that relies on the knowledge of every programmer.

like image 2
James Curran Avatar answered Nov 18 '22 20:11

James Curran