J
Jamie Julius
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
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