locked
How to make a ref int?

    Question

  • I am passing an ref int to a class instantiation.  When I change x in DialogBox, I would like the value y to be changed also.  How do I do this?  Can it be done?  Obviously, if y was wrapped in a class, it would be straight forward but I don't know how to do this with a variable.

     

    int y = 1;

    DialogBox dlg(y);

    dlg.DoSomething();

     

    // y is equal to 1 but I want it to be equal to 2

     

    class DialogBox

    {

      int x;

      DialogBox(ref int x)

      {

        this.x = x;

      }

      void DoSomething()

      {

        x = 2;

      }

    }

    Tuesday, November 13, 2007 12:40 AM

Answers

  • That's not what the "ref" keyword does.  If you want to have a value that is referenced by more than one class you'll need to wrap it with some sort of class that handles changing the value so all other classes can see it.

    Tuesday, November 13, 2007 12:42 AM
    Moderator
  • Hi,

     

    Just try this code.

     

    class DialogBox

    {

    int x;

    public DialogBox(ref int x)

    {

    x = this.x;

    }

    public void DoSomething()

    {

    x = 2;

    }

    }

     

    int y = 1;                 //here value of y is 1

    DialogBox dlg = new DialogBox(ref y);               //after this exacution value of y is changed to 0

    dlg.DoSomething();

     

     

    Hope this solve your query.

     

    Regards,

    Manju Sandhu

     

     

    Tuesday, November 13, 2007 4:13 AM
  • "My main application instantiates a dialog box.  While the dialog box has focus, I want to change a value in my main application from the dialog box"

     

    One might suggest that the "old c++ way" be abandoned and the "new C# event way" be embraced.

     

    Code Block

    delegate void DialogBoxChangedEventHandler(int newValue);

    class DialogBox

    {

      public event DialogBoxChangedEventHandler Changed;

      private void FireChanged() { if (Changed != null) Changed(); }

    }

     

     

     

     

    .. main application ..

     

    Code Block

    DialogBox db = new DialogBox();

    db.Changed += delegate(int newValue) { i = newValue; }

    db.ShowDialog();

     

     

    Thursday, November 15, 2007 7:44 PM

All replies

  • That's not what the "ref" keyword does.  If you want to have a value that is referenced by more than one class you'll need to wrap it with some sort of class that handles changing the value so all other classes can see it.

    Tuesday, November 13, 2007 12:42 AM
    Moderator
  • If a pass a ref int to a function, and change the ref value in that function, then the value sent would change.  What I want is a pointer (like in C++) in the class so I change the value sent.  Is that possible with C# or am I force to wrap the value in a class?

     

    Tuesday, November 13, 2007 12:56 AM
  • Hi,

     

    Just try this code.

     

    class DialogBox

    {

    int x;

    public DialogBox(ref int x)

    {

    x = this.x;

    }

    public void DoSomething()

    {

    x = 2;

    }

    }

     

    int y = 1;                 //here value of y is 1

    DialogBox dlg = new DialogBox(ref y);               //after this exacution value of y is changed to 0

    dlg.DoSomething();

     

     

    Hope this solve your query.

     

    Regards,

    Manju Sandhu

     

     

    Tuesday, November 13, 2007 4:13 AM
  • Sounds like he wants something like this...

        class Integer
        {
            public int value;
        }

        class DialogBox
        {
            Integer x;

            public DialogBox(ref Integer x)
            {
                x = this.x = new Integer();
            }

            public void DoSomething()
            {
                x.value = 2;
            }
        }

     
         Integer y = new Integer();
         DialogBox dlg = new DialogBox(ref y);           
         dlg.DoSomething();
     
    Tuesday, November 13, 2007 6:11 AM
  • Why make things more complicated than they have to be?

    Code Block

    int y = 1;

    DialogBox dlg(y);

    dlg.DoSomething();

    y = dlg.X; //y is now 2

     

    class DialogBox

    {

      int x;

      public int X { get { return x; } }


      DialogBox(int x)

      {

        this.x = x;

      }


      void DoSomething()

      {

        x = 2;

      }

    }


    Guess I just don't see why you need to do this...

    HTH,
    Kent
    Tuesday, November 13, 2007 2:42 PM
  •  Kent Boogaart wrote:
    Why make things more complicated than they have to be?

    Code Block

    int y = 1;

    DialogBox dlg(y);

    dlg.DoSomething();

    y = dlg.X; //y is now 2

     

    class DialogBox

    {

      int x;

      public int X { get { return x; } }


      DialogBox(int x)

      {

        this.x = x;

      }


      void DoSomething()

      {

        x = 2;

      }

    }


    Guess I just don't see why you need to do this...


    It's an old practice from C/C++ where you want to return more than one variable from a function.  Rather than creating a whole class for a few ints and floats, you can just pass the pointer of the variable to the function and modify the value inside the function without having to pass back classes, arrrays, and such.  To me it's merely another way to optimize your code -- saving memory because of less items declared on the heap/stack.

    The ref or out keywords should accomplish what he's trying to do, as far as I was aware anyways.
    Tuesday, November 13, 2007 3:35 PM
  •  jlac1024 wrote:
     Kent Boogaart wrote:
    Why make things more complicated than they have to be?

    Code Block

    int y = 1;

    DialogBox dlg(y);

    dlg.DoSomething();

    y = dlg.X; //y is now 2

     

    class DialogBox

    {

      int x;

      public int X { get { return x; } }


      DialogBox(int x)

      {

        this.x = x;

      }


      void DoSomething()

      {

        x = 2;

      }

    }


    Guess I just don't see why you need to do this...



    It's an old practice from C/C++ where you want to return more than one variable from a function.  Rather than creating a whole class for a few ints and floats, you can just pass the pointer of the variable to the function and modify the value inside the function without having to pass back classes, arrrays, and such.  To me it's merely another way to optimize your code -- saving memory because of less items declared on the heap/stack.

    The ref or out keywords should accomplish what he's trying to do, as far as I was aware anyways.

    The OP is asking that two variables change upon a single assignment.  ref/out won't do that.

     

    Remember, C# isn't C/C++.  The OP can do what he wants with pointers and unsafe code...

    Tuesday, November 13, 2007 3:43 PM
    Moderator
  •  Peter Ritchie wrote:


    The OP is asking that two variables change upon a single assignment.  ref/out won't do that.

     

    Remember, C# isn't C/C++.  The OP can do what he wants with pointers and unsafe code...




    I understand that, I misread his question.  But he can do it with pointers, regardless of it being C# -- there's nothing wrong with it.
    Tuesday, November 13, 2007 4:20 PM
  •  jlac1024 wrote:

    The ref or out keywords should accomplish what he's trying to do, as far as I was aware anyways.


    Not in this case because the OP is passing the int reference to a constructor and then modifying it in a separate method. C# does not allow you to store references to value types as fields, so this cannot work. In other words, you can't do this:

    Code Block
    int myInt = 0;
    Example example = new Example(ref myInt);
    example.Method2();

    class Example

    {

    private ref int _i;


    void Method1(ref int i)
    {

    _i = i;

    }


    void Method2()
    {

    _i = _i + 1;

    }

    }


    but you can do this:

    Code Block

    int myInt = 0;

    Example example = new Example();

    example.Method(ref myInt);

    //myInt now equals 1


    class Example

    {

    void Method(ref int i)
    {

    ++i;

    }

    }


    HTH,
    Kent
    Tuesday, November 13, 2007 4:44 PM
  •  jlac1024 wrote:
     Peter Ritchie wrote:


    The OP is asking that two variables change upon a single assignment.  ref/out won't do that.

     

    Remember, C# isn't C/C++.  The OP can do what he wants with pointers and unsafe code...




    I understand that, I misread his question.  But he can do it with pointers, regardless of it being C# -- there's nothing wrong with it.
    There's nothing wrong with it, unless the OP wants the code to operate in a partial-trust environment (unsafe code requires elevated privileges), needs the assembly to be verifiable, or needs the code to be CLS-compliant.
    Tuesday, November 13, 2007 4:57 PM
    Moderator
  •  Peter Ritchie wrote:


    There's nothing wrong with it, unless the OP wants the code to operate in a partial-trust environment (unsafe code requires elevated privileges), needs the assembly to be verifiable, or needs the code to be CLS-compliant.



    Interesting, I didn't know that.  Do you have, or know of, any documentation I can read about that?
    Tuesday, November 13, 2007 5:39 PM
  • I believe Manju Sandu answered my problem.

     

    I should have stated my question better.  My main application instantiates a dialog box.  While the dialog box has focus, I want to change a value in my main application from the dialog box.  From Manju Sandu's reply, x = this.x solves this problem.

     

    Although this solves my problem, is this the correct way to code?

     

     

    Code Block

    class Program

    {

      static void Main(string[] args)

      {

        int y = 1;

     

        DB db = new DB(ref y);

     

        // In my application, I want y = 2 before returning to this point,

        //  which it now does

     

        return;

      }

      class DB

      {

        int x = 0;

     

        public DB(ref int x)

        {

          x = this.x;

          x = 2;

        }

      }

    }

     

     

     

    Wednesday, November 14, 2007 5:19 PM
  • Well, I gave it a try in my application, stated above, and it had some unexpected results.  As stated

     

    DialogBox dlg = new DialogBox(ref y);               //after this exacution value of y is changed to 0

     

    The y value comes back as zero.

     

    Guess I better wrap up the values in a class.

     

    Thanks for all of your help.

    Wednesday, November 14, 2007 10:35 PM
  • Hi,

     

    You wll get the answer 2 if you just change the sequence of execution like this

     

     

    class Program

    {

      static void Main(string[] args)

      {

        int y = 1;

     

        DB db = new DB(ref y);

     

        // In my application, I want y = 2 before returning to this point,

        //  which it now does

     

        return;

      }

      class DB

      {

        int x = 0;

     

        public DB(ref int x)

        {

          this.x = 2;

          x = this.x;

        }

      }

    }

     

    Regards,

    Manju Sandhu

    Thursday, November 15, 2007 4:38 AM
  • "My main application instantiates a dialog box.  While the dialog box has focus, I want to change a value in my main application from the dialog box"

     

    One might suggest that the "old c++ way" be abandoned and the "new C# event way" be embraced.

     

    Code Block

    delegate void DialogBoxChangedEventHandler(int newValue);

    class DialogBox

    {

      public event DialogBoxChangedEventHandler Changed;

      private void FireChanged() { if (Changed != null) Changed(); }

    }

     

     

     

     

    .. main application ..

     

    Code Block

    DialogBox db = new DialogBox();

    db.Changed += delegate(int newValue) { i = newValue; }

    db.ShowDialog();

     

     

    Thursday, November 15, 2007 7:44 PM
  • There are times I just love C# and then there are times like this.  Thanks for the suggestion and it is probably the "correct" way to accomplish my original problem.  But I just might wrap the variable in a class to make is easier to read.

    Saturday, November 17, 2007 3:42 PM
  • OK, I thought I would fix the problem by wrapping the value in a class.  Well, I was actually sending 2 float values and I decided to shove them into System.Drawing.PointF.  Now I assumed PointF was a reference type BUT IT WAS NOT!  It seems it is a value type.  So I made a new class called PointD and wrapped the 2 values and everyting worked fine.  First, am I nuts?  Why is PointF a class that acts like a value type.  Second, how can I determine if a class is a reference type or value type in the future?

     

    Wednesday, November 21, 2007 6:29 PM
  • PointF is a value type because it meets the criteria of acting like a primitive type.

    See Value Type Usage Guidelines in the MSDN Library

    http://msdn2.microsoft.com/en-us/library/y23b5415(vs.71).aspx

     

    To determine if a type is a value type you can test it:

    int a=0;

    if (a is ValueType) // warning : The given expression is always of the provided ('System.ValueType') type

     

    Edit:

    You can also simply right-click on the type ("int" in the above example) in Visual Studio and select "Go To Definition". If it's a struct, it's a value type, if it's class, it's a reference type.

     

     

    Wednesday, November 21, 2007 7:57 PM
  • Thanks for the link.

    Wednesday, November 21, 2007 9:39 PM
  •  conrarn wrote:

    Why is PointF a class that acts like a value type.
    Second, how can I determine if a class is a reference type or value type in the future?


    To address your first question: System.Drawing.PointF is not a class, it is a struct.
    And your second question: You can find this out by reading the documentation, such as this.

    Thursday, November 22, 2007 10:57 AM
  • I ended up using Tergiver's suggestion although it looks a little different.

    Code Block

    Calling application

     

    private void legendPositionToolStripMenuItem_Click(object sender, EventArgs e)

    {

      double originalAutoLegendPositionX = autoLegendPositionX;

      double originalAutoLegendPositionY = autoLegendPositionY;

     

      StripperLegendsPositionForm dlg = new StripperLegendsPositionForm();

     

      dlg.X = autoLegendPositionX;

      dlg.Y = autoLegendPositionY;

     

      dlg.Apply += new EventHandler(legendPositionDialogApply);

     

      if (dlg.ShowDialog() == DialogResult.OK)

      {

        autoLegendPositionX = dlg.X;

        autoLegendPositionY = dlg.Y;

      }

      else

      {

        autoLegendPositionX = originalAutoLegendPositionX;

        autoLegendPositionY = originalAutoLegendPositionY;

      }

     

      dlg.Dispose();

     

      panel.Invalidate();

    }

     

    private void legendPositionDialogApply(object sender, EventArgs e)

    {

      StripperLegendsPositionForm dlg = (StripperLegendsPositionForm)sender;

     

      autoLegendPositionX = dlg.X;

      autoLegendPositionY = dlg.Y;

     

      panel.Invalidate();

    }

     

     

    Dialog Box

     

    public partial class StripperLegendsPositionForm : Form

    {

      public event EventHandler Apply;

     

      double x;

      double y;

     

      public double X {set {x = value;} get {return x;}}

      public double Y {set {y = value;} get {return y;}}

     

      private void buttonApply_Click(object sender, EventArgs e)

      {

        if (Apply != null) Apply(this, new EventArgs());

      }

    }

     

     

     

     

     

    Sunday, December 02, 2007 5:57 PM
  •  conrarn wrote:

    I ended up using Tergiver's suggestion although it looks a little different.

     

    I'm glad to hear it. This provides a little better decoupling between the objects. Now the Position Form doesn't care what information is needed by any of its consumers (one consumer in this case). It can just do its job and notify anyone interested that changes have occurred.

    Monday, December 03, 2007 6:22 PM