Rolls, Robert [mailto:[EMAIL PROTECTED]] wrote:

> Do people still use the constructor to define default values
> to members or has the default constructor been depreciated?
> Are there any reasons not to use to the following?
>
> public byte[] arr = new byte[1024];
>
> rather than
>
> public byte[] arr = null;
>
> then within the constructor
> arr = new byte[1024];

Robert, first a disclaimer: the following are results of the C# compiler,
other compilers may do things differently. That said:

When member variables are initialized at declaration time, the
initialization code is injected into *each* constructor[1a][1b]. So you
technically get a little IL bloat, where as if you deferred to your own
default constructor from overloaded constructors you can avoid that[2a][2b].
Then again depending on the JIT implementation, if it doesn't inline the
default constructor... you'd pay a runtime perf. hit for the jmp. My guess
is the MS JIT, on a release build, would inline such a scenario, but perhaps
someone more intimately familiar with the JIT can fill us in. Out of
curiousity I just tried another scenario[3a][3b] and it looks like the C#
compiler is smart enough to automagically avoid injecting initialization
code into any constructor that defers to another constructor.

Next, notice the initialization code is also for declaration time
initialized variables is executed *prior* to the base class' constructor
being called, whereas if you actually initialized the member variables in
the constructor the base constructor would be called first. I don't see this
making a big difference other than maybe you could be wasting some time and,
depending on how the CLR is implemented, some memory (assuming the member
variables are reference types) if the base class' constructor threw an
exception. The memory would of course be cleaned up eventually at the next
GC anyway, but it was allocated none-the-less.

Beyond that... I really don't see any differences other than syntatic
preference. So going on the assumption that the JIT will inline deferring
calls to other constructors, #2 looks to be the best approach. You avoid IL
bloat and the base class' constructor is called first which avoids any
potential time or memory wasted by declaration time initialized variables.

HTH,
Drew
.NET MVP

[1a]
<codeSnippet language="C#">
public class MyClass1
{
  private int someValue = 1;
  private int someOtherValue;

  public MyClass1()
  {
  }

  public MyClass1(int someOtherValue)
  {
    this.someOtherValue = someOtherValue;
  }
}
</codeSnippet>

[1b]
<codeSnippet language="CIL">
  .class public auto ansi beforefieldinit MyClass
         extends [mscorlib]System.Object
  {
    .field private int32 someValue
    .field private int32 someOtherValue
    .method public hidebysig specialname rtspecialname
            instance void  .ctor() cil managed
    {
      // Code size       14 (0xe)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.1
      IL_0002:  stfld      int32 Gnutella.Net.classes.MyClass::someValue
      IL_0007:  ldarg.0
      IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
      IL_000d:  ret
    } // end of method MyClass::.ctor

    .method public hidebysig specialname rtspecialname
            instance void  .ctor(int32 someOtherValue) cil managed
    {
      // Code size       21 (0x15)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.1
      IL_0002:  stfld      int32 Gnutella.Net.classes.MyClass::someValue
      IL_0007:  ldarg.0
      IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
      IL_000d:  ldarg.0
      IL_000e:  ldarg.1
      IL_000f:  stfld      int32
Gnutella.Net.classes.MyClass::someOtherValue
      IL_0014:  ret
    } // end of method MyClass::.ctor

  } // end of class MyClass
</codeSnippet>

[2a]
<codeSnippet language="C#">
  public class MyClass2
  {
    private int someValue;
    private int someOtherValue;

    public MyClass2()
    {
      this.someValue = 1;
    }

    public MyClass2(int someOtherValue) : this()
    {
      this.someOtherValue = someOtherValue;
    }
}
</codeSnippet>

[2b]
<codeSnippet language="CIL">
  .class public auto ansi beforefieldinit MyClass2
         extends [mscorlib]System.Object
  {
    .field private int32 someValue
    .field private int32 someOtherValue
    .method public hidebysig specialname rtspecialname
            instance void  .ctor() cil managed
    {
      // Code size       14 (0xe)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
      IL_0006:  ldarg.0
      IL_0007:  ldc.i4.1
      IL_0008:  stfld      int32 Gnutella.Net.classes.MyClass2::someValue
      IL_000d:  ret
    } // end of method MyClass2::.ctor

    .method public hidebysig specialname rtspecialname
            instance void  .ctor(int32 someOtherValue) cil managed
    {
      // Code size       14 (0xe)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  call       instance void
Gnutella.Net.classes.MyClass2::.ctor()
      IL_0006:  ldarg.0
      IL_0007:  ldarg.1
      IL_0008:  stfld      int32
Gnutella.Net.classes.MyClass2::someOtherValue
      IL_000d:  ret
    } // end of method MyClass2::.ctor

  } // end of class MyClass2
</codeSnippet>

[3a]
<codeSnippet language="C#">
  public class MyClass3
  {
    private int someValue;
    private int someOtherValue;

    public MyClass3()
    {
    }

    public MyClass2(int someOtherValue) : this()
    {
      this.someOtherValue = someOtherValue;
    }
}
</codeSnippet>

[3b]
<codeSnippet language="CIL">
  .class public auto ansi beforefieldinit MyClass3
         extends [mscorlib]System.Object
  {
    .field private int32 someValue
    .field private int32 someOtherValue
    .method public hidebysig specialname rtspecialname
            instance void  .ctor() cil managed
    {
      // Code size       14 (0xe)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.1
      IL_0002:  stfld      int32 Gnutella.Net.classes.MyClass3::someValue
      IL_0007:  ldarg.0
      IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
      IL_000d:  ret
    } // end of method MyClass3::.ctor

    .method public hidebysig specialname rtspecialname
            instance void  .ctor(int32 someOtherValue) cil managed
    {
      // Code size       14 (0xe)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  call       instance void
Gnutella.Net.classes.MyClass3::.ctor()
      IL_0006:  ldarg.0
      IL_0007:  ldarg.1
      IL_0008:  stfld      int32
Gnutella.Net.classes.MyClass3::someOtherValue
      IL_000d:  ret
    } // end of method MyClass3::.ctor

  } // end of class MyClass3
</codeSnippet>

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to