1

I Read this StackOverflow Question And i read this blog here

I couldn't understand completely. Here are my doubts.

 struct S
{
    private int x;
    private int y;

    public int X { get { return x; } }
    public int Y { get { return y; } }

    public S(int x, int y, bool panic)
    {          
        this.x = x;
        this.y = y;

        if (panic)
            throw new Exception();
    }
}

static class P
{
    static void Main()
    {
        S s = default(S);

        try
        {                

            s = new S(1, 2, false);

            Console.WriteLine("{0}, {1}", s.X, s.Y);

            s = new S(3, 4, true);
        }
        catch
        {
            Console.WriteLine("{0}, {1}", s.X, s.Y);
        }

        Console.ReadLine();
    }

}

Here before throwing exception i assigned the values. But why is it not assigning to the object s i mean in the console i written in the catch block, says (1,2).

Because it is initialized again in the second line , and called the constructor with (3,4). so how it is (1,2).

Somehow i cant understand this.

And also,

Therefore, using the new operator on a value type allocates no additional memory. Rather, the memory already allocated for the value is used.

In that blog , the answer is No.

If that is the case, is it initializing with new memory. If so, how comes (1,2) is coming in the catch block.

As i am new to C# i am not able understand this.

I know its silly doubt, but someone please help me in understanding this concept.

Community
  • 1
  • 1
shanmugharaj
  • 3,814
  • 7
  • 42
  • 70
  • 2
    As you're throwing an exception in the constructor, the new initialization, `new S(3, 4, true)` "never happened", as an object lifetime is only starting when its construction is successfully finished – Paolo Falabella Feb 12 '15 at 14:57
  • you did not return a new object with 3,4 yet. you crash before assignation. do it doesn't get to reset `s` – Franck Feb 12 '15 at 14:58

5 Answers5

4

Quoted from the blog Debunking another myth about value types:

The C# specification is clear on this point:

"If T is a struct type, an instance of T is created by allocating a temporary local variable"

That is, the statement

s = new S(123, 456);

actually means:

  • Determine the location referred to by s.
  • Allocate a temporary variable t of type S, initialized to its default value.
  • Run the constructor, passing a reference to t for "this".
  • Make a by-value copy of t to s.

You are throwing the exception during the third stage:

  • Run the constructor, passing a reference to t for "this"

Meaning the last stage, which copies to s never occurs, hence you see the current values of s which in your case is 1, 2.

Lukazoid
  • 19,016
  • 3
  • 62
  • 85
2

Because it is initialized again in the second line , and called the constructor with (3,4).

You've called the constructor, but the constructor itself hasn't finished - so the assignment to s never takes place.

This of this:

s = new S(3, 4, true);

As equivalent to :

// Create the new value
S tmp = new S(3, 4, true);
// Copy it into the s variable
s = tmp;

The first statement never completes, so the assignment doesn't occur... so you still see the first value of s in the catch block.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks Jon for replying. "Therefore, using the new operator on a value type allocates no additional memory. Rather, the memory already allocated for the value is used." How i will assure this is false ? – shanmugharaj Feb 12 '15 at 15:04
  • And also the object s and its members will be in stack or heap ? – shanmugharaj Feb 12 '15 at 15:05
  • @shan: It's not an object, it's just an instance of S - and it'll be on the stack. As for how you can be assured that it's false *when it needs to be* - you need to trust that the compiler will do the right thing to make sure the language rules are obeyed. If there's no way that you could observe the same memory being reused, then the compiler is free to do that. If you *can* observe it (e.g. by using `s` in a `catch` block in your case) then it can't. – Jon Skeet Feb 12 '15 at 15:07
0

In the console you print s.X and s.Y. This is the first s from

s = new S(1, 2, false);

the second assignment is never executed, because the Exception is thrown.

DrKoch
  • 9,556
  • 2
  • 34
  • 43
0

The Exception is Happening before the assignment to the S on the left side of the equals sign.

So your catch block writes out the original values from the previous assignment.

The Capital S variable is a Type and the small s is an instance.

Sql Surfer
  • 1,344
  • 1
  • 10
  • 25
0

Struct constructors are implemented as methods which take the structure being constructed as an implied ref parameter. In many cases, a compiler will implement a statement like:

s = new StructType(4);

as equivalent to

var temp = default(StructType);
StructType..ctor(out temp, 4);  // Not possible with C# syntax
s = temp;

There are, however, some cases where it does not do so, but instead simply does:

StructType..ctor(out s, 4);

and where this may be observable, especially when interacting with code written in other languages which do not honor the attribute C# uses to mark out parameters.

For example, although it is not possible to write an implementation of IDictionary.TryGetValue in C# which won't store a default(TValue) to its out parameter, that parameter will be see by other languages as a ref parameter; consequently, an implementation written in another language may return without writing anything to it. If a struct constructor passes this to the TryGetValue method of a passed-in IDictionary but doesn't do anything else, the actual behavior of struct construction may be observed.

supercat
  • 77,689
  • 9
  • 166
  • 211