By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,723 Members | 1,185 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,723 IT Pros & Developers. It's quick & easy.

"new" on value types

P: n/a
Consider the following struct:

struct TestStruct
{
public int a, b, c;

public TestStruct(int a, int b, int c)
{
this.a = a;

if (b == 6)
{
throw new ArgumentException("I don't like 6", "b");
}

this.b = b;
this.c = c;
}
}

The C# spec says in section 7.5.10.1:

The run-time processing of an object-creation-expression of the form new
T(A) ... If T is a struct-type:
An instance of type T is created by allocating a temporary local variable.

From this I would assume that if I write the following:

TestStruct ts = new TestStruct();

ts = new TestStruct(1, 2, 3);
ts = new TestStruct(3, 6, 9);

The compiler should invoke the constructor on temporary instances and
subsequently copy the temporaries into "ts". This would imply that if the
constructor throws an exception, "ts" will remain with its original value.

However, the C# compiler seems to pass "ts" itself into the constructor as
the "this" instance (i.e., not a temporary):

IL_0008: ldloca.s ts
IL_000a: ldc.i4.1
IL_000b: ldc.i4.2
IL_000c: ldc.i4.3
IL_000d: call instance void Testing.Item03/TestStruct::.ctor(int32, int32,
int32)

Indeed, if the constructor throws an exception after changing some of the
fields, "ts" results in an inconsistent state.

Basically, I'm curious as to anyone's opinion as to whether this is a
compiler bug, or is the assignment of the value produced by the 'new'
operator a special case.

For comparison, if I change the above to the following:

ts = newTestStruct(1, 2, 3);

where the following is defined:

static TestStruct newTestStruct(int a, int b, int c)
{
return new TestStruct(a, b, c);
}

I get the consistent behavior I was hoping for.

Thanks,

Jamie


Nov 16 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
> The C# spec says in section 7.5.10.1:

The run-time processing of an object-creation-expression of the form new
T(A) ... If T is a struct-type:
An instance of type T is created by allocating a temporary local variable.

From this I would assume that if I write the following:

TestStruct ts = new TestStruct();

ts = new TestStruct(1, 2, 3);
ts = new TestStruct(3, 6, 9);

The compiler should invoke the constructor on temporary instances and
subsequently copy the temporaries into "ts". This would imply that if the
constructor throws an exception, "ts" will remain with its original value.

However, the C# compiler seems to pass "ts" itself into the constructor as
the "this" instance (i.e., not a temporary):

IL_0008: ldloca.s ts
IL_000a: ldc.i4.1
IL_000b: ldc.i4.2
IL_000c: ldc.i4.3
IL_000d: call instance void Testing.Item03/TestStruct::.ctor(int32, int32,
int32)

Indeed, if the constructor throws an exception after changing some of the
fields, "ts" results in an inconsistent state.

Basically, I'm curious as to anyone's opinion as to whether this is a
compiler bug, or is the assignment of the value produced by the 'new'
operator a special case.


Jamie,

I've tested your code and can confirm that C# compiler does not use a
temporary variable in value type initialization. It seems that reusing value
types is rather risky then, especially that the docs says that temp variable
IS used.

What is more interesting is that VB.NET compiler does use a temporary
variable for initialization!
In following example (where Class1 is a struct):

Dim c As Class1

c = New Class1

c = New Class1(1, 2, 3)

you get:

..method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01
00 00 00 )
// Code size 26 (0x1a)
.maxstack 4
.locals init ([0] valuetype ConsoleApplication1.Class1 c,
[1] valuetype ConsoleApplication1.Class1 _Vb_t_record_0)
IL_0000: nop
IL_0001: ldloca.s _Vb_t_record_0
IL_0003: initobj ConsoleApplication1.Class1
IL_0009: ldloc.1
IL_000a: stloc.0
IL_000b: ldloca.s _Vb_t_record_0
IL_000d: ldc.i4.1
IL_000e: ldc.i4.2
IL_000f: ldc.i4.3
IL_0010: call instance void
ConsoleApplication1.Class1::.ctor(int32,
int32,
int32)
IL_0015: nop
IL_0016: ldloc.1
IL_0017: stloc.0
IL_0018: nop
IL_0019: ret
} // end of method Module1::Main

where as you can see the _vb_t_record_0 is the temporary vatiable that is
initialized as copied after each initialization:

....

ldloc.1

stloc.0

....

To me it seems that C# compiler should do exactly the same, while it does
not. I really think that this behavior deserves a fundamental explanation! I
hope someone else will comment this one.

Regards,

Wiktor Zychla
Nov 16 '05 #2

P: n/a
Jamie Julius <ja***@netvision.net.il> wrote:
Consider the following struct:
<snip>
Basically, I'm curious as to anyone's opinion as to whether this is a
compiler bug, or is the assignment of the value produced by the 'new'
operator a special case.


It looks like a compiler bug to me - logically the assignment really
shouldn't happen until after the constructor has terminated normally.

Have you reported it to MS? Also, have you checked the behaviour on the
beta of VS 2005?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #3

P: n/a
Thanks, Jon and Wiktor for your support on this!
Have you reported it to MS?
No, I haven't. What's the best way to report bugs like this?
Also, have you checked the behaviour on the beta of VS 2005?
No, I haven't done that either. I currently don't have the beta installed.
I'll ask a friend.

Meanwhile, if anyone out there would like to check this on VS 2005, that
would be interesting...

I know that C++ gives some latitude to compilers to optimize away
temporaries. Do you know if similar guidelines exist for C# compilers? I
couldn't find anything in the spec about this. Anyway, I built the test
program with optimizations turned off, so it's unlikely that that's what's
going on.

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Jamie Julius <ja***@netvision.net.il> wrote:
Consider the following struct:


<snip>
Basically, I'm curious as to anyone's opinion as to whether this is a
compiler bug, or is the assignment of the value produced by the 'new'
operator a special case.


It looks like a compiler bug to me - logically the assignment really
shouldn't happen until after the constructor has terminated normally.

Have you reported it to MS? Also, have you checked the behaviour on the
beta of VS 2005?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #4

P: n/a
Jamie Julius <ja***@netvision.net.il> wrote:
Thanks, Jon and Wiktor for your support on this!
Have you reported it to MS?


No, I haven't. What's the best way to report bugs like this?


If you're able to check with the beta of VS 2005, use
http://lab.msdn.microsoft.com/produc...k/default.aspx

Here's a short but complete program which they might find useful (just
your code with the appropriate Main etc):

using System;

struct TestStruct
{
public int a, b, c;

public TestStruct(int a, int b, int c)
{
this.a = a;

if (b == 6)
{
throw new ArgumentException("I don't like 6", "b");
}

this.b = b;
this.c = c;
}

static void Main()
{
TestStruct ts = new TestStruct (1, 2, 3);
try
{
ts = new TestStruct (3, 6, 9);
}
catch
{
// Yes, I know...
}

Console.WriteLine ("{0} {1} {2}", ts.a, ts.b, ts.c);
}
}
Also, have you checked the behaviour on the beta of VS 2005?


No, I haven't done that either. I currently don't have the beta installed.
I'll ask a friend.

Meanwhile, if anyone out there would like to check this on VS 2005, that
would be interesting...

I know that C++ gives some latitude to compilers to optimize away
temporaries. Do you know if similar guidelines exist for C# compilers? I
couldn't find anything in the spec about this. Anyway, I built the test
program with optimizations turned off, so it's unlikely that that's what's
going on.


C# is usually much stricter about what the compiler can and can't do,
fortunately. I'm 99% sure this is a real bug.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #5

P: n/a
Here is the VS2005 generated IL. Don't quite understand if this fixes
the problem, but thought someone could look at it...

..method private hidebysig static void Main() cil managed
{
.custom instance void
[mscorlib]System.STAThreadAttribute::.ctor()
.entrypoint
.maxstack 4
.locals (
GenericsPerf.TestStruct struct1)
L_0000: ldloca.s struct1
L_0002: initobj GenericsPerf.TestStruct
L_0008: ldloca.s struct1
L_000a: ldc.i4.1
L_000b: ldc.i4.2
L_000c: ldc.i4.3
L_000d: call instance void GenericsPerf.TestStruct::.ctor(int32,
int32, int32)
L_0012: nop
L_0013: ldloca.s struct1
L_0015: ldc.i4.3
L_0016: ldc.i4.6
L_0017: ldc.i4.s 9
L_0019: call instance void GenericsPerf.TestStruct::.ctor(int32,
int32, int32)
L_001e: nop
L_001f: call void
[System.Windows.Forms]System.Windows.Forms.Application::EnableVisualStyl es()
L_0024: nop
L_0025: ret
}

Jamie Julius wrote:
Thanks, Jon and Wiktor for your support on this!
Have you reported it to MS?
No, I haven't. What's the best way to report bugs like this?
Also, have you checked the behaviour on the beta of VS 2005?


No, I haven't done that either. I currently don't have the beta

installed. I'll ask a friend.

Meanwhile, if anyone out there would like to check this on VS 2005, that would be interesting...

I know that C++ gives some latitude to compilers to optimize away
temporaries. Do you know if similar guidelines exist for C# compilers? I couldn't find anything in the spec about this. Anyway, I built the test program with optimizations turned off, so it's unlikely that that's what's going on.

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Jamie Julius <ja***@netvision.net.il> wrote:
Consider the following struct:


<snip>
Basically, I'm curious as to anyone's opinion as to whether this is a compiler bug, or is the assignment of the value produced by the 'new' operator a special case.


It looks like a compiler bug to me - logically the assignment really shouldn't happen until after the constructor has terminated normally.
Have you reported it to MS? Also, have you checked the behaviour on the beta of VS 2005?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


Nov 16 '05 #6

P: n/a
Looks like a v1.x issue only.
Works as documented using v2.0 Beta (VS2005 CTP December drop).

Willy.

"Jamie Julius" <ja***@netvision.net.il> wrote in message
news:cv**********@news2.netvision.net.il...
Thanks, Jon and Wiktor for your support on this!
Have you reported it to MS?


No, I haven't. What's the best way to report bugs like this?
Also, have you checked the behaviour on the beta of VS 2005?


No, I haven't done that either. I currently don't have the beta installed.
I'll ask a friend.

Meanwhile, if anyone out there would like to check this on VS 2005, that
would be interesting...

I know that C++ gives some latitude to compilers to optimize away
temporaries. Do you know if similar guidelines exist for C# compilers? I
couldn't find anything in the spec about this. Anyway, I built the test
program with optimizations turned off, so it's unlikely that that's what's
going on.

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Jamie Julius <ja***@netvision.net.il> wrote:
Consider the following struct:


<snip>
Basically, I'm curious as to anyone's opinion as to whether this is a
compiler bug, or is the assignment of the value produced by the 'new'
operator a special case.


It looks like a compiler bug to me - logically the assignment really
shouldn't happen until after the constructor has terminated normally.

Have you reported it to MS? Also, have you checked the behaviour on the
beta of VS 2005?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


Nov 16 '05 #7

P: n/a
Thanks, cyost.

In this IL it looks like the bug still exists.

However, Willy in the post following yours claims that in his version (v2.0
Beta - VS2005 CTP December drop) it has been fixed. Which version did you
test with?

<cy***@charter.net> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Here is the VS2005 generated IL. Don't quite understand if this fixes
the problem, but thought someone could look at it...

.method private hidebysig static void Main() cil managed
{
.custom instance void
[mscorlib]System.STAThreadAttribute::.ctor()
.entrypoint
.maxstack 4
.locals (
GenericsPerf.TestStruct struct1)
L_0000: ldloca.s struct1
L_0002: initobj GenericsPerf.TestStruct
L_0008: ldloca.s struct1
L_000a: ldc.i4.1
L_000b: ldc.i4.2
L_000c: ldc.i4.3
L_000d: call instance void GenericsPerf.TestStruct::.ctor(int32,
int32, int32)
L_0012: nop
L_0013: ldloca.s struct1
L_0015: ldc.i4.3
L_0016: ldc.i4.6
L_0017: ldc.i4.s 9
L_0019: call instance void GenericsPerf.TestStruct::.ctor(int32,
int32, int32)
L_001e: nop
L_001f: call void
[System.Windows.Forms]System.Windows.Forms.Application::EnableVisualStyl es()
L_0024: nop
L_0025: ret
}

Jamie Julius wrote:
Thanks, Jon and Wiktor for your support on this!
> Have you reported it to MS?


No, I haven't. What's the best way to report bugs like this?
> Also, have you checked the behaviour on the beta of VS 2005?


No, I haven't done that either. I currently don't have the beta

installed.
I'll ask a friend.

Meanwhile, if anyone out there would like to check this on VS 2005,

that
would be interesting...

I know that C++ gives some latitude to compilers to optimize away
temporaries. Do you know if similar guidelines exist for C#

compilers? I
couldn't find anything in the spec about this. Anyway, I built the

test
program with optimizations turned off, so it's unlikely that that's

what's
going on.

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
> Jamie Julius <ja***@netvision.net.il> wrote:
>> Consider the following struct:
>
> <snip>
>
>> Basically, I'm curious as to anyone's opinion as to whether this is a >> compiler bug, or is the assignment of the value produced by the 'new' >> operator a special case.
>
> It looks like a compiler bug to me - logically the assignment really > shouldn't happen until after the constructor has terminated normally. >
> Have you reported it to MS? Also, have you checked the behaviour on the > beta of VS 2005?
>
> --
> Jon Skeet - <sk***@pobox.com>
> http://www.pobox.com/~skeet
> If replying to the group, please do not mail me too

Nov 16 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.