473,405 Members | 2,261 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

"new" on value types

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
7 1306
> 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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
by: Rv5 | last post by:
Rookie c++ question, but Ive spent the last 5 years doing Java, where everytime I created an object I used new. In c++ I can create my objects without and its confusing me just a little. I have...
1
by: Jean Stax | last post by:
Hi ! A couple of pretty basic questions: Value types: As far as I understand, when I create value type without "new" syntax the object is considered as unutilized. Consequently, I have to...
6
by: peter.xiau | last post by:
I found that std::vector<int> v(10) ; will automatically initiallize every elem to 0 in the vector, I check the source code (VS.NET2003), and I found a line of code like this *T = new T() ; ...
4
by: Ben R. | last post by:
I'm curious about the differeng behavior of the "new" keyword when dealing with value versus object types. If I'm correct, when I do: dim x as integer There's no need for "new" to be called...
37
by: jht5945 | last post by:
For example I wrote a function: function Func() { // do something } we can call it like: var obj = new Func(); // call it as a constructor or var result = Func(); // call it as...
36
by: Pat | last post by:
Hi, I've run into a strange problem, but one that seems like it might be fairly common. I have a single base class, from which several other classes are derived. To keep the example simple,...
4
by: Asm23 | last post by:
Hi i'm using intel P4. when I write the statement like char *p=new char what's the p value, is it aligned by 4 bytes? that's is p%4==0? and, now I'm using the Intel SSE2 instruction to do...
12
by: Robert Fuchs | last post by:
Hello, This example: public class BaseC { public int x; public void Invoke() {} } public class DerivedC : BaseC
30
by: Medvedev | last post by:
i see serveral source codes , and i found they almost only use "new" and "delete" keywords to make they object. Why should i do that , and as i know the object is going to be destroy by itself at...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.