Use of struct in Dynamic code

Nov 18, 2010 at 3:37 PM

I'm having a bit of confusion using a struct in a dynamic C# code.  Hopefully someone can explain what is going on or let me know if this is a bug in the DLR.

Here's the case:  I have a POD struct called Real.  And a class Record made up of this and similar structs.  See the VERY STRIPPED DOWN example.  Please don't flame the style.  I'm just trying to show the problem.

 struct Real
    {
        public double real;
        public Real(double real)    { this.real = real;  }
    }

    class Record
    {
        public Real r;
        public Record(double r)     { this.r = new Real(r); }
        }
        public void Test(double origval, double newval)
        {
            if (this.r.real == newval)
                Console.WriteLine("r = newval-test passed\n");
            else if (this.r.real == origval)
                Console.WriteLine("r = origval-test failed\n");
            else
                Console.WriteLine("r = neither-test failed\n");
        }
    }

And here's the test code:

    class Program
    {
        static void Main(string[] args)
        {
            double origval = 8.0;
            double newval = 5.0;

            // TEST 1: This works - create known type Record, change value
            Record record1 = new Record(origval);
            record1.r.real = newval;        // change value
            record1.Test(origval, newval);

            // TEST 2: This doesn't work.  change value is not making any change!
            dynamic dynrecord2 = new Record(origval);
            dynrecord2.r.real = newval;     // change value
            dynrecord2.Test(origval, newval);

            // TEST 3: This works - create dynamic type Record, change value
            dynamic dynrecord3 = new Record(origval);
            dynamic r = dynrecord3.r;       // copy out value
            r.real = newval;                // change copy
            dynrecord3.r = r;               // copy in modified value
            dynrecord3.Test(origval, newval);

            // TEST 4:  This works.  change value is not making any change!
            dynamic dynrecord4 = new Record(origval);
            dynrecord4.r = new Real(newval);     // change value
            dynrecord4.Test(origval, newval);

            Console.Read();
        }
    }

So what is the matter with Test 2?  Why can't I set a public value in a public struct field in a class using dynamic?   And why can I using a non-dynamic type?

By the way, what's the correct term to use for a non-dynamic type? 

Thanks for your explanations.

Max

Coordinator
Nov 18, 2010 at 4:35 PM

Hi, Max. I'm adding the new DLR owners who may not be on this list yet. More importantly this looks to be more a C# dynamic binding issue/decision rather than a straight DLR issue, and these guys own the c# compiler/binder too :-). One of them should be able to tell you what is up with your test 2.

The term for non-dynamic is static. Static is overloaded in a few ways. For what you're asking, there's static typing (and pre-determining behaviors at compile-time, modulo some virtual dispatch of methods) and there's dynamic typing (determining at runtime, where it is not provably correct to decide at compile time, what the right behavior is).

Cheers,

Bill

From: MRY92 [mailto:notifications@codeplex.com]
Sent: Thursday, November 18, 2010 7:38 AM
To: Bill Chiles
Subject: Use of struct in Dynamic code [dlr:235185]

From: MRY92

I'm having a bit of confusion using a struct in a dynamic C# code. Hopefully someone can explain what is going on or let me know if this is a bug in the DLR.

Here's the case: I have a POD struct called Real. And a class Record made up of this and similar structs. See the VERY STRIPPED DOWN example. Please don't flame the style. I'm just trying to show the problem.

struct Real
{
public double real;
public Real(double real) { this.real = real; }
}

class Record
{
public Real r;
public Record(double r) { this.r = new Real(r); }
}
public void Test(double origval, double newval)
{
if (this.r.real == newval)
Console.WriteLine("r = newval-test passed\n");
else if (this.r.real == origval)
Console.WriteLine("r = origval-test failed\n");
else
Console.WriteLine("r = neither-test failed\n");
}
}

And here's the test code:

class Program
{
static void Main(string[] args)
{
double origval = 8.0;
double newval = 5.0;

// TEST 1: This works - create known type Record, change value
Record record1 = new Record(origval);
record1.r.real = newval; // change value
record1.Test(origval, newval);

// TEST 2: This doesn't work. change value is not making any change!
dynamic dynrecord2 = new Record(origval);
dynrecord2.r.real = newval; // change value
dynrecord2.Test(origval, newval);

// TEST 3: This works - create dynamic type Record, change value
dynamic dynrecord3 = new Record(origval);
dynamic r = dynrecord3.r; // copy out value
r.real = newval; // change copy
dynrecord3.r = r; // copy in modified value
dynrecord3.Test(origval, newval);

// TEST 4: This works. change value is not making any change!
dynamic dynrecord4 = new Record(origval);
dynrecord4.r = new Real(newval); // change value
dynrecord4.Test(origval, newval);

Console.Read();
}
}

So what is the matter with Test 2? Why can't I set a public value in a public struct field in a class using dynamic? And why can I using a non-dynamic type?

By the way, what's the correct term to use for a non-dynamic type?

Thanks for your explanations.

Max

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Nov 18, 2010 at 4:37 PM
That is what I believe that is happening in your test case 2:
dynrecord2.r got compiled into a delegate that returns a copy of Real. So dynrecord2.r.real = newval is assigned on the copy.
Li Chen

On Thu, Nov 18, 2010 at 7:37 AM, MRY92 <notifications@codeplex.com> wrote:

From: MRY92

I'm having a bit of confusion using a struct in a dynamic C# code. Hopefully someone can explain what is going on or let me know if this is a bug in the DLR.

Here's the case: I have a POD struct called Real. And a class Record made up of this and similar structs. See the VERY STRIPPED DOWN example. Please don't flame the style. I'm just trying to show the problem.

struct Real
{
public double real;
public Real(double real) { this.real = real; }
}

class Record
{
public Real r;
public Record(double r) { this.r = new Real(r); }
}
public void Test(double origval, double newval)
{
if (this.r.real == newval)
Console.WriteLine("r = newval-test passed\n");
else if (this.r.real == origval)
Console.WriteLine("r = origval-test failed\n");
else
Console.WriteLine("r = neither-test failed\n");
}
}

And here's the test code:

class Program
{
static void Main(string[] args)
{
double origval = 8.0;
double newval = 5.0;

// TEST 1: This works - create known type Record, change value
Record record1 = new Record(origval);
record1.r.real = newval; // change value
record1.Test(origval, newval);

// TEST 2: This doesn't work. change value is not making any change!
dynamic dynrecord2 = new Record(origval);
dynrecord2.r.real = newval; // change value
dynrecord2.Test(origval, newval);

// TEST 3: This works - create dynamic type Record, change value
dynamic dynrecord3 = new Record(origval);
dynamic r = dynrecord3.r; // copy out value
r.real = newval; // change copy
dynrecord3.r = r; // copy in modified value
dynrecord3.Test(origval, newval);

// TEST 4: This works. change value is not making any change!
dynamic dynrecord4 = new Record(origval);
dynrecord4.r = new Real(newval); // change value
dynrecord4.Test(origval, newval);

Console.Read();
}
}

So what is the matter with Test 2? Why can't I set a public value in a public struct field in a class using dynamic? And why can I using a non-dynamic type?

By the way, what's the correct term to use for a non-dynamic type?

Thanks for your explanations.

Max

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Coordinator
Nov 18, 2010 at 5:15 PM

Forwarding for Mads who doesn't have a codeplex identity …

From: Mads Torgersen
Sent: Thursday, November 18, 2010 9:06 AM
To: Bill Chiles; dlr@discussions.codeplex.com; Avner Aharoni; Alex Turner; Theo Yaung; Peter Hauge
Subject: RE: Use of struct in Dynamic code [dlr:235185]

Hi Max,

This is a little unfortunate but by design. In

dynrecord2.r.real = newval; // change value

The value of dynrecord2.r gets boxed, which means copied into its own heap object. That copy is the one getting modified, not the original that you subsequently test.

This is a consequence of the very “local” way in which C# dynamic works. Think about a statement like the above – there are two fundamental ways that we could attack that:

1) Realize at compile time that something dynamic is going on, and essentially move the whole statement to be bound at runtime

2) Bind individual operations at runtime when their constituents are dynamic, returning something dynamic that may in turn cause things to be bound at runtime

In C# we went with the latter, which is nicely compositional, and makes it easy to describe dynamic in terms of the type system, but has some drawbacks – such as boxing of resulting value types for instance.

So what you are seeing is a result of this design choice.

Thanks,

Mads

From: Bill Chiles
Sent: Thursday, November 18, 2010 8:36 AM
To: dlr@discussions.codeplex.com; Avner Aharoni; Alex Turner; Theo Yaung; Peter Hauge; Mads Torgersen
Subject: RE: Use of struct in Dynamic code [dlr:235185]

Hi, Max. I'm adding the new DLR owners who may not be on this list yet. More importantly this looks to be more a C# dynamic binding issue/decision rather than a straight DLR issue, and these guys own the c# compiler/binder too :-). One of them should be able to tell you what is up with your test 2.

The term for non-dynamic is static. Static is overloaded in a few ways. For what you're asking, there's static typing (and pre-determining behaviors at compile-time, modulo some virtual dispatch of methods) and there's dynamic typing (determining at runtime, where it is not provably correct to decide at compile time, what the right behavior is).

Cheers,

Bill

From: MRY92 [mailto:notifications@codeplex.com]
Sent: Thursday, November 18, 2010 7:38 AM
To: Bill Chiles
Subject: Use of struct in Dynamic code [dlr:235185]

From: MRY92

I'm having a bit of confusion using a struct in a dynamic C# code. Hopefully someone can explain what is going on or let me know if this is a bug in the DLR.

Here's the case: I have a POD struct called Real. And a class Record made up of this and similar structs. See the VERY STRIPPED DOWN example. Please don't flame the style. I'm just trying to show the problem.

struct Real
{
public double real;
public Real(double real) { this.real = real; }
}

class Record
{
public Real r;
public Record(double r) { this.r = new Real(r); }
}
public void Test(double origval, double newval)
{
if (this.r.real == newval)
Console.WriteLine("r = newval-test passed\n");
else if (this.r.real == origval)
Console.WriteLine("r = origval-test failed\n");
else
Console.WriteLine("r = neither-test failed\n");
}
}

And here's the test code:

class Program
{
static void Main(string[] args)
{
double origval = 8.0;
double newval = 5.0;

// TEST 1: This works - create known type Record, change value
Record record1 = new Record(origval);
record1.r.real = newval; // change value
record1.Test(origval, newval);

// TEST 2: This doesn't work. change value is not making any change!
dynamic dynrecord2 = new Record(origval);
dynrecord2.r.real = newval; // change value
dynrecord2.Test(origval, newval);

// TEST 3: This works - create dynamic type Record, change value
dynamic dynrecord3 = new Record(origval);
dynamic r = dynrecord3.r; // copy out value
r.real = newval; // change copy
dynrecord3.r = r; // copy in modified value
dynrecord3.Test(origval, newval);

// TEST 4: This works. change value is not making any change!
dynamic dynrecord4 = new Record(origval);
dynrecord4.r = new Real(newval); // change value
dynrecord4.Test(origval, newval);

Console.Read();
}
}

So what is the matter with Test 2? Why can't I set a public value in a public struct field in a class using dynamic? And why can I using a non-dynamic type?

By the way, what's the correct term to use for a non-dynamic type?

Thanks for your explanations.

Max

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Nov 18, 2010 at 8:08 PM

Thanks, Bill.

Nov 18, 2010 at 8:29 PM

 

Thanks, Mads. 

Talk about from the horse's mouth, so to speak. 

Can I post your answer on StackOverflow where I have the same question?  Or you can and get the brownie points.

Regards,

Max

Coordinator
Nov 18, 2010 at 9:41 PM

Hey, Max. Mads says to feel free to post it and get the brownie points :-). That was nice of you to ask.

Cheers,

Bill

From: MRY92 [mailto:notifications@codeplex.com]
Sent: Thursday, November 18, 2010 12:29 PM
To: Bill Chiles
Subject: Re: Use of struct in Dynamic code [dlr:235185]

From: MRY92

Thanks, Mads.

Talk about from the horse's mouth, so to speak.

Can I post your answer on StackOverflow where I have the same question? Or you can and get the brownie points.

Regards,

Max

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com