C# marshal-by-reference



  • // In this example, frmEntry has a public decimal named amount.
    

    frmEntry entry_form = new frmEntry();
    if (entry_form.ShowDialog() == DialogResult.Yes)
    {
    // Actual intent. Causes CS0197.
    lblValue.Text = discount_form.amount.ToString("f");

    // This works.
    decimal a = entry_form.amount;
    lblValue.Text = a.ToString("f");
    
    // Microsoft's "fix"
    // See http://msdn.microsoft.com/library/en-us/cscomp/html/vcerrCompilerErrorCS0197.asp
    lblValue.Text = ((decimal)((object)(entry_form.amount))).ToString("f");
    

    }



  • Sounds like that should be a property, not a member variable.  If not, a method works but it will be dirty.

    Looks like another case of a leaky abstraction.  Marshal-by-reference...well I'm not familiar with COM enough to know what that means, unfortunately.



  • I have no idea. The problem seems to be the .ToString, because in the real code, there is also a public boolean that I can access just fine. (eg. if (entry_form.percent) lblValue.Text += "%";)



  • Makes sense to me.  If frmEntry inherits from MarshalByRefObject then .NET considers it to be capable of being a proxy.  Therefore, you can't pass a field of it because you might be crossing process boundaries (which would break things).  So you have to extract the value from its object.  Assigning the value to a local variable makes a copy on the stack that you can use.  Casting the decimal to a double would create a copy on the stack and then you can use that copy.

    For C++ people:  Think about passing a pointer to a variable to another machine or another process on the same machine.  The pointer would mean nothing.  C# recognizes that you might be doing that and tells you no.  So you have to pass by value, not by reference.  It's just a rare side effect of trying to hide pointers from you.



  • @danguy said:

    // In this example, frmEntry has a public decimal named amount.

    frmEntry entry_form = new frmEntry();
    if (entry_form.ShowDialog() == DialogResult.Yes)
    {
    // Actual intent. Causes CS0197.
    lblValue.Text = discount_form.amount.ToString("f");

    // This works.
    decimal a = entry_form.amount;
    lblValue.Text = a.ToString("f");
    
    // Microsoft's "fix"
    // See http://msdn.microsoft.com/library/en-us/cscomp/html/vcerrCompilerErrorCS0197.asp
    lblValue.Text = ((decimal)((object)(entry_form.amount))).ToString("f");
    

    }

    Don't know much about C#, but in your failing code you're referencing "discount_form", but in both the workaround and MS's "fix" you're referencing "entry_form" ...

     



  • Well, I guess that is what happens when you are not careful enough when anonymizing code. Thay are all the same form, and it is just a regular WinForm.



  • @danguy said:

    // In this example, frmEntry has a public decimal named amount.

    frmEntry entry_form = new frmEntry();
    if (entry_form.ShowDialog() == DialogResult.Yes)
    {
    // Actual intent. Causes CS0197.
    lblValue.Text = discount_form.amount.ToString("f");

    // This works.
    decimal a = entry_form.amount;
    lblValue.Text = a.ToString("f");
    
    // Microsoft's "fix"
    // See http://msdn.microsoft.com/library/en-us/cscomp/html/vcerrCompilerErrorCS0197.asp
    lblValue.Text = ((decimal)((object)(entry_form.amount))).ToString("f");
    

    }

    <FONT color=#ffffff><troll></FONT>The real WTF is C#<FONT color=#ffffff></troll></FONT>



  • @Some Idiot said:

    <font color="#ffffff"><troll></font>The real WTF is C#<font color="#ffffff"></troll></font>



    Nice tags. :-P


Log in to reply