Using ref

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Arjen

    Using ref

    Hi,

    Form a performance perspective, is it wise to use the ref statement as much
    as possible?

    Thanks!
    Arjen

  • Steve Harclerode

    #2
    Re: Using ref

    The objects themselves are passed by reference anyway, so I would think that
    using "ref" would actually slow things down a tiny bit (adds one more level
    of indirection.

    I only use "ref" when I need to reseat the variable to point to a different
    object.

    - Steve

    "Arjen" <boah123@hotmai l.comwrote in message
    news:1B8D9143-DA8C-4B5A-807B-DA05E6F908E0@mi crosoft.com...
    Hi,
    >
    Form a performance perspective, is it wise to use the ref statement as
    much
    as possible?
    >
    Thanks!
    Arjen

    Comment

    • Jon Skeet [C# MVP]

      #3
      Re: Using ref

      Steve Harclerode <Lizard.That.Wa s@hot.mail.comw rote:
      The objects themselves are passed by reference anyway
      No, they're not. The references are passed by value. There's a big
      difference. See
      Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

      I only use "ref" when I need to reseat the variable to point to a different
      object.
      Exactly.

      --
      Jon Skeet - <skeet@pobox.co m>
      Web site: http://www.pobox.com/~skeet
      Blog: http://www.msmvps.com/jon_skeet
      C# in Depth: http://csharpindepth.com

      Comment

      • Arjen

        #4
        Re: Using ref


        "Jon Skeet [C# MVP]" <skeet@pobox.co mschreef in bericht
        news:MPG.22d5ff b147cd0b7cded@m snews.microsoft .com...
        Steve Harclerode <Lizard.That.Wa s@hot.mail.comw rote:
        >The objects themselves are passed by reference anyway
        >
        No, they're not. The references are passed by value. There's a big
        difference. See
        Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

        >
        >I only use "ref" when I need to reseat the variable to point to a
        >different
        >object.
        >
        Exactly.
        >
        --
        Jon Skeet - <skeet@pobox.co m>
        Web site: http://www.pobox.com/~skeet
        Blog: http://www.msmvps.com/jon_skeet
        C# in Depth: http://csharpindepth.com
        Thank you!

        Comment

        • raylopez99

          #5
          Re: Using ref

          On Jul 2, 2:12 pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
          --
          I agree with Jon Skeet here. A ref should be used when you have a
          reference-type object passed to your function, which usually means
          something that is instantiated with "new" in the function. But, if
          you don't use "new" in your method/function for the object passed to
          it, then use the default pass by value. Interestingly enough, both
          pass by value and pass by reference *will* both alter the object
          passed *outside* the function/method--the opposite is usually implied
          in most textbook examples. In most examples it is stated that only
          pass by reference will alter the object-- with usually the famous
          'swap variables' example using 'temp' given--but what most people
          don't realize is that this swap variable example is using 'new' inside
          the function/method (check it out next time you see it, and you'll see
          that's the case), which is exactly when you should use 'ref'--
          otherwise stick to the default pass-by-value. If 'new' is not being
          used for the object passed, use the default pass-by-value, as it's
          slightly faster, as implied in this thread. The only exception to the
          above is when primitive values (int, double, etc) are passed to a
          function/method--but here, this seems to be an exception because these
          are value-type parameters stored on the stack rather than heap, so
          boxing/unboxing is involved. Technically, you could box these
          primitive value-type parameters as reference-type objects, then there
          would be no 'exception'. Anyway, it usually doesn't make sense to
          refer to 'ref' when passing an int parameter to a method/function
          anyway, so this is really not an exception to the rule.

          In short, the rule is this: when using 'new' inside your method, to
          instantiate a object being passed to the method (in the parameters
          list), then use the 'ref' keyword in the parameters, to pass by
          reference, otherwise, stick with the default (no keyword) pass-by-
          value.

          If the above doesn't make sense, don't worry about it--just keep
          programming and it will become clear eventually.

          Ray Lopez
          [C# N00b MVP]

          Comment

          • Steve Harclerode

            #6
            Re: Using ref

            I've read the page, but I still don't see how my languaging would be
            considered different than "references are passed by value". What part of
            what I wrote isn't correct?

            Genuinely interested,
            Steve

            "Jon Skeet [C# MVP]" <skeet@pobox.co mwrote in message
            news:MPG.22d5ff b147cd0b7cded@m snews.microsoft .com...
            Steve Harclerode <Lizard.That.Wa s@hot.mail.comw rote:
            >The objects themselves are passed by reference anyway
            >
            No, they're not. The references are passed by value. There's a big
            difference. See
            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

            >

            Comment

            • Jon Skeet [C# MVP]

              #7
              Re: Using ref

              On Jul 3, 7:33 am, "Steve Harclerode" <Camel.Software ...@hot.mail.co m>
              wrote:
              I've read the page, but I still don't see how my languaging would be
              considered different than "references are passed by value". What part of
              what I wrote isn't correct?
              When a parameter is passed by reference, that means that changes to
              the parameter are reflected in the variable used as the argument. When
              a reference is passed by value, that's not the case.

              So consider this code:

              public void Swap (object a, object b)
              {
              object tmp = a;
              a = b;
              b = a;
              }

              If the parameter were passed by reference by default, that would work.
              As it is, it does nothng.

              The *object* isn't actually passed at all, which is another reason
              that "objects are passed by reference" is incorrect. In particular,
              consider the case where the reference is actually null. What's being
              passed and in what way at that point?

              It's a clearer and more accurate mental model to talk about references
              being passed by value. It avoids confusing people who understand what
              "by reference" means, and would expect the Swap method above to work
              when presented with your description. (I've seen this happen on
              various occasions.) It also makes it very confusing when you add the
              "ref" parameter for a reference type - if things were already being
              passed by reference, what would adding "ref" do?

              Jon

              Comment

              • Peter Duniho

                #8
                Re: Using ref

                On Wed, 02 Jul 2008 23:33:57 -0700, Steve Harclerode
                <Camel.Software .Co@hot.mail.co mwrote:
                I've read the page, but I still don't see how my languaging would be
                considered different than "references are passed by value". What part of
                what I wrote isn't correct?
                You wrote "objects are passed by reference". But _all_ parameters,
                including references to objects, are passed _by value_, except when using
                "ref" and "out" of course.

                The fact that the value you're passing is a reference does not make the
                parameter a "by reference" parameter, nor does it mean that the object is
                passed by reference.

                IMHO, Jon's article does in fact explain this.

                Pete

                Comment

                • Steve Harclerode

                  #9
                  Re: Using ref

                  "Jon Skeet [C# MVP]" <skeet@pobox.co mwrote in message
                  news:efd1cd11-4ac9-4d62-ad01-631f589dc205@s5 0g2000hsb.googl egroups.com...
                  public void Swap (object a, object b)
                  {
                  object tmp = a;
                  a = b;
                  b = a;
                  }
                  >
                  If the parameter were passed by reference by default, that would work.
                  As it is, it does nothng.
                  Thinking back on my Pascal days, by golly you're right (you probably knew
                  that already).
                  It's a clearer and more accurate mental model to talk about references
                  being passed by value. It avoids confusing people who understand what
                  It is a better mental model, I'll use it the next time I have to mentor a
                  new person. God help the others I've already worked with. Actually, they
                  seem to be doing all right, so hopefully they absorbed the correct
                  information somewhere.
                  :-)

                  - Steve


                  Comment

                  • Hilton

                    #10
                    Re: Using ref

                    Jon,

                    I have to disagree with you that objects themselves are passed by value.
                    Passing by value means that you pass the value; i.e. a byte[] (or Vector, or
                    Hashtable) being passed as value passes the entire thing - that doesn't
                    happen. Also, passing by value means that the thing cannot be changed;
                    hence passing by value not reference. But when you do "method (list)",
                    method can change list because a reference to the list is being passed, not
                    the list (aka value). C# simple passes a reference to the object which is
                    the same as C passing in a pointer to the data. And the method cannot
                    change the reference in C# just as the method in C cannot change the pointer
                    (from the caller's point of view) - same thing.

                    Pass by reference:
                    C# - passes a reference to the data (not the data) and the data can be
                    changed by the method
                    C - passes a pointer to the data (not the data) and the data can be changed
                    by the method

                    The example you give on your page "method (StringBuilder x)" then "x = null"
                    is exactly the same as C having "method (int *x)", then "x = NULL"; i.e.
                    pass by reference. If you view "x" as a reference to the StringBuilder
                    object, then you're passing the object by reference (which you said did not
                    happen). If you view "x" as the actual StringBuilder object, then the VM is
                    effectively passing &x (C terminology) - again, by reference. It uses
                    ldloca.s which is defined as "Loads the address of the local variable at a
                    specific index onto the evaluation stack, short form." - same as C.

                    Apart from ints, floats, etc, C# passes all objects by reference. "ref"
                    simply passes the address of the reference thereby allowing the method to
                    change it (exactly the same as C). "out" is the same as "ref" except that
                    the method is forced, by the compiler, to assign a value to the parameter.

                    How is this C code that uses pass by reference:

                    byte* b = {some array of bytes};
                    method (b);

                    ....different to this C# code?

                    byte[] b = new byte[]{some array of bytes};
                    method (b);

                    In a meeting, would you ever say "Add the two string references together to
                    get the filename"? I wouldn't, I'd say "Add the two strings together to get
                    the filename". So, if we view "s" as a string, then "method (s)" is pass by
                    reference.

                    Jon, Peter, before you reply, I know that most of the literature out there
                    agrees with your point of view, so no need to rehash what they have already
                    written. Maybe it's just me, but I cannot see how C# passes objects by
                    value.

                    Hilton


                    Comment

                    • Peter Duniho

                      #11
                      Re: Using ref

                      On Thu, 03 Jul 2008 00:36:38 -0700, Hilton <nospam@nospam. comwrote:
                      Jon,
                      >
                      I have to disagree with you that objects themselves are passed by value.
                      Jon never said they were. In fact, he pointedly stated that objects are
                      themselves never passed at all in C#.

                      I agree with this viewpoint, and it's consistent with the usage of the
                      terms in the C# specification, as well as MSDN's documentation of C#.
                      Passing by value means that you pass the value; i.e. a byte[] (or
                      Vector, or
                      Hashtable) being passed as value passes the entire thing - that doesn't
                      happen.
                      Straw man. You're arguing a point that was never in contention.
                      Also, passing by value means that the thing cannot be changed;
                      That's not what "passing by value" means. It's true that the original
                      argument cannot be changed, but that's just a side-effect of what "by
                      value" really is: making a copy of the original argument and passing that
                      to the method.
                      hence passing by value not reference. But when you do "method (list)",
                      method can change list because a reference to the list is being passed,
                      not
                      the list (aka value).
                      The method can _not_ change the original argument that was passed, which
                      is what distinguishes passing "by value" and "by reference".
                      C# simple passes a reference to the object which is
                      the same as C passing in a pointer to the data.
                      Not really. In C, you have the option of passing the data as a complete
                      copy. This simply doesn't exist in C#. The reference _is_ the data. But
                      more importantly, C++ distinguishes between passing a pointer by value,
                      and passing a pointer by reference. It's true that before C++ came along
                      and introduced the passing of parameters by reference, people would just
                      pass a pointer and call that "by reference". But it's not really what was
                      happening. In C/C++ when you pass a pointer without the "&" as part of
                      the parameter declaration, you are passing a pointer _by value_.
                      And the method cannot
                      change the reference in C# just as the method in C cannot change the
                      pointer
                      (from the caller's point of view) - same thing.
                      That's right. Because in both cases the parameter is passed by value, the
                      original storage for that value cannot be modified by the method/function
                      being called.
                      Pass by reference:
                      C# - passes a reference to the data (not the data) and the data can be
                      changed by the method
                      Wrong. The fact that a reference is being passed does not mean the
                      parameter is being passed "by reference".
                      C - passes a pointer to the data (not the data) and the data can be
                      changed
                      by the method
                      Again, wrong. The pointer is being passed by value.
                      The example you give on your page "method (StringBuilder x)" then "x =
                      null"
                      is exactly the same as C having "method (int *x)", then "x = NULL"; i.e.
                      pass by reference.
                      Wrong. Both are passing by value. That's why the caller's copy of the
                      value is not changed when the method assigns "x" to "null".
                      If you view "x" as a reference to the StringBuilder
                      object, then you're passing the object by reference
                      Saying the same thing over and over again isn't going to make it true.
                      The fact that a reference is being passed does not make it "passing by
                      reference". The reference is passed by value.
                      (which you said did not
                      happen). If you view "x" as the actual StringBuilder object,
                      Why would we do that? The actual object is accessible only through a
                      reference. There is no way to put the object itself into a variable.
                      then the VM is
                      effectively passing &x (C terminology) - again, by reference. It uses
                      ldloca.s which is defined as "Loads the address of the local variable at
                      a
                      specific index onto the evaluation stack, short form." - same as C.
                      "It uses"? What uses? You haven't posted any code that you could be
                      referring to. What example is it that you are saying uses "ldloca.s"?
                      Are you comparing this to managed code? If not, how can that be "same as
                      C"?

                      In any case, the "ldloca.s" instruction is used when you pass by
                      reference, yes. But that's only when you use the "ref" or "out" keyword.
                      Try it and see. If you just pass an object reference by value, a plain
                      "ldloc" instruction is used, not "ldloca".

                      If this is the basis of your argument, then I'd say you just blew up your
                      own argument. By your own description, since "ldloca" is _not_ used when
                      you pass by value, even when the argument is a object reference, obviously
                      the object reference is being passed by value, not by reference.
                      Apart from ints, floats, etc, C# passes all objects by reference.
                      No. C# passes _everything_ by value, unless you state otherwise with
                      "ref" or "out". The fact that the value is sometimes a reference is
                      immaterial. It is still passed by value.
                      "ref"
                      simply passes the address of the reference thereby allowing the method to
                      change it (exactly the same as C).
                      That's right...it passes a _reference_ to the reference. That is, using
                      "ref" is how you pass "by reference". If you're not using "ref" or "out",
                      you're not passing by reference.
                      "out" is the same as "ref" except that
                      the method is forced, by the compiler, to assign a value to the
                      parameter.
                      And the caller is not.
                      How is this C code that uses pass by reference:
                      >
                      byte* b = {some array of bytes};
                      method (b);
                      That's not C code that uses pass by reference. It's passing a pointer by
                      value.
                      ...different to this C# code?
                      >
                      byte[] b = new byte[]{some array of bytes};
                      method (b);
                      It's exactly the same and both are passing by value.
                      In a meeting, would you ever say "Add the two string references together
                      to
                      get the filename"? I wouldn't, I'd say "Add the two strings together to
                      get
                      the filename".
                      I would never say "add the two strings" or "add the two string
                      references". I would say "concatenat e the two strings". But how is this
                      at all related to the question of passing by value or by reference?
                      So, if we view "s" as a string, then "method (s)" is pass by
                      reference.
                      Huh? If we view "s" as a string, then "method(s)" is passing the object
                      "s" by value. Even using your incorrect terminology, the "method(s)" can
                      only be "pass by reference" is we view "s" as a reference.
                      Jon, Peter, before you reply, I know that most of the literature out
                      there
                      agrees with your point of view, so no need to rehash what they have
                      already
                      written.
                      I beg to differ. As long as you insist on posting a claim contrary to the
                      truth, there will be a need to "rehash what they ahve already written".

                      All that literature out there that agrees with our point of view, it
                      didn't just happen by accident. There's a _reason_ that the vast majority
                      of C# documentation (and _all_ of the definitive documentation, such as
                      the specification itself) agrees with this point of view.
                      Maybe it's just me, but I cannot see how C# passes objects by
                      value.
                      It'd be one thing if you were approaching this naïvely. We could just
                      explain how things really work, and you could get on with whatever it is
                      you're doing. But you've obviously put a lot of effort and thought into
                      your argument. Which means you're simply not paying attention to reality.

                      Don't get confused by the fact that the same word is used in two different
                      ways. That's a huge mistake on your part.

                      And consider this: if you are already always passing objects by reference,
                      then what does it mean to use "ref" when you are passing an object? Are
                      you passing "by reference by reference"?

                      Pete

                      Comment

                      • Hilton

                        #12
                        Re: Using ref

                        Jon Skeet wrote:
                        Hilton wrote:
                        >I have to disagree with you that objects themselves are passed by value.
                        >Where did I say that they were? I said that *references* are passed by
                        >value. Objects aren't passed at all.
                        You replied to Steve:

                        Steve Harclerode <Lizard.That.Wa s@hot.mail.comw rote:
                        The objects themselves are passed by reference anyway
                        No, they're not.
                        ---

                        I then made the assumption that if the object wasn't passed by reference, it
                        is passed by value - which is it?

                        [zap your reply]

                        Jon, I totally 'see' you view on this (which seems to be consistent with
                        many/most others - i.e. I acknowledge that I am in the minority here). My
                        point is that a method works on data and I care about the data, I care about
                        the stuff that is in arrays, lists etc. Now, even though you assert that "C
                        doesn't have pass by reference at all.", for decades millions of people were
                        taught the difference between passing by reference and passing by value
                        using C, were they wrong? If I have data, and I don't pass that data to a
                        method, but rather pass a reference/pointer (whatever the syntax), then (in
                        my mind) it is pass by reference. C# and C really aren't that different in
                        these terms, just that it is hidden (thankfully) - I don't think that the
                        syntax of the language should change the terminology of what really is
                        happening under the covers. The key here is that you're thinking strictly
                        in terms of the parameters, I'm thinking in terms of the data.

                        Wow, I'm still trying to wrap my head around your "C doesn't have pass by
                        reference at all" comment. I understand your logic of it, but it sure as
                        heck doesn't make any sense to me. Having said that, I think Wikipedia sums
                        up our two opposing views in this line: "Java is a call-by-value language,
                        but since most Java expressions are references to anonymous objects, it
                        frequently displays call-by-reference semantics without the need for any
                        explicit reference syntax."

                        Hilton


                        Hilton


                        Comment

                        • Jon Skeet [C# MVP]

                          #13
                          Re: Using ref

                          On Jul 3, 11:09 am, "Hilton" <nos...@nospam. comwrote:
                          Jon Skeet wrote:
                          Hilton wrote:
                          I have to disagree with you that objects themselves are passed by value.
                          Where did I say that they were? I said that *references* are passed by
                          value. Objects aren't passed at all.
                          >
                          You replied to Steve:
                          >
                          Steve Harclerode <Lizard.That... .@hot.mail.comw rote:
                          The objects themselves are passed by reference anyway
                          >
                          No, they're not.
                          ---
                          >
                          I then made the assumption that if the object wasn't passed by reference,it
                          is passed by value - which is it?
                          Well, you could have read the *very next sentence* in my reply, which
                          explained what actually happens:

                          "The references are passed by value."

                          Your assumption reminds me of the "When did you stop beating your
                          wife?" question.
                          [zap your reply]
                          >
                          Jon, I totally 'see' you view on this (which seems to be consistent with
                          many/most others - i.e. I acknowledge that I am in the minority here).  My
                          point is that a method works on data and I care about the data, I care about
                          the stuff that is in arrays, lists etc.  Now, even though you assert that "C
                          doesn't have pass by reference at all.", for decades millions of people were
                          taught the difference between passing by reference and passing by value
                          using C, were they wrong?
                          Yes. If they'd read K&R, I believe they'd have seen something
                          explicitly saying that C only supports pass by value. (I don't have a
                          copy to hand, but I'm pretty sure I've seen it there before.) You can
                          *simulate* pass by reference in C, but it's not true pass by
                          reference.
                           If I have data, and I don't pass that data to a
                          method, but rather pass a reference/pointer (whatever the syntax), then (in
                          my mind) it is pass by reference.
                          Then your mind is wrong by the technical definitions of pass by
                          reference.
                          See http://en.wikipedia.org/wiki/Evaluation_strategy
                          > C# and C really aren't that different in
                          these terms, just that it is hidden (thankfully) - I don't think that the
                          syntax of the language should change the terminology of what really is
                          happening under the covers.
                          Whether the language supports pass by reference or not is defined by
                          the language specification. C# *does* support pass by reference using
                          the "ref" keyword. C doesn't support it (directly - you can emulate it
                          but that's not the same thing).
                          > The key here is that you're thinking strictly
                          in terms of the parameters, I'm thinking in terms of the data.
                          I'm thinking in terms of the meanings of technical terms, which are
                          how we communicate.
                          Wow, I'm still trying to wrap my head around your "C doesn't have pass by
                          reference at all" comment.  I understand your logic of it, but it sure as
                          heck doesn't make any sense to me.
                          That's because I believe you've been misunderstandin g the meaning of
                          "pass by reference" as indeed many people do.
                          Pass by reference has a very specific meaning, and it isn't directly
                          supported by the C language. You have to work round the lack of
                          support by explicitly passing (and receiving) a pointer *by value*.

                          It's not just me that says that C doesn't directly have pass-by-
                          reference semantics though:
                          http://en.wikipedia.org/wiki/C_(programming_language)



                          As I say, I believe it's explicitly stated in K&R as well.
                          > Having said that, I think Wikipedia sums
                          up our two opposing views in this line: "Java is a call-by-value language,
                          but since most Java expressions are references to anonymous objects, it
                          frequently displays call-by-reference semantics without the need for any
                          explicit reference syntax."
                          Yes, the effects can be similar in many cases. That doesn't mean it's
                          the same thing. Calling C#'s default behaviour "pass by reference" can
                          be very confusing (I've seen several people get confused by it) and
                          often leads to the mistaken belief that adding the "ref" modifier for
                          a parameter which uses a reference type makes no difference. After
                          all, if it's already being passed by reference, what difference could
                          "ref" make?

                          Once you understand that the value of a variable (or any expression)
                          is either a value type value or a reference (including null) you end
                          up with a much more consistent mental model which works well with
                          parameters, assignment, GC etc. Trying to think of the world in terms
                          where the value of a variable is the object itself falls down all over
                          the place, as well as being further removed from the technical
                          details. Why do you want to push a more complicated world view which
                          just doesn't stand up to scrutiny?

                          Jon

                          Comment

                          • Hilton

                            #14
                            Re: Using ref

                            Peter Duniho wrote:
                            Hilton wrote:
                            What example is it that you are saying uses "ldloca.s"? Are you
                            comparing this to managed code? If not, how can that be "same as C"?
                            >
                            In any case, the "ldloca.s" instruction is used when you pass by
                            reference, yes. But that's only when you use the "ref" or "out" keyword.
                            My point is that the C# call "method (ref x)" is defined by
                            you/Jon/community as being pass by reference, yet the C call "method (&x)"
                            is defined by you/Jon/community as being pass by value - they're doing
                            EXACTLY the same thing. Both simply take the address of x and pass it
                            along. Does a prettier syntax changes the entire concept? And if
                            Microsoft has used "&" instead of "ref" in its definition of the C#
                            language, would that now mean that the C# call "method (&x)" was now pass by
                            value???

                            Pete, really, I don't want to spend more of your time or my time on this.
                            In my mind (which I agree probably doesn't fit the pure definition of the
                            pass-by definitions), if I pass a reference or pointer to my chunk of data,
                            I'm passing by reference (the focus being on the data, not the actual
                            parameter). I think millions of other people think that way too since
                            pass-by-reference has been taught for decades when discussing C, but
                            apparently that capability never existed.

                            Hilton


                            Comment

                            • Marc Gravell

                              #15
                              Re: Using ref

                              if I pass a reference or pointer to my chunk of data,
                              I'm passing by reference
                              You can keep repeating this, but it doesn't make it true. And re-
                              iterating it only adds confusion for new C# developers; one of the
                              reasons so many people get it wrong is because others (like yourself)
                              seem to be going out of their way to keep the myth alive.

                              In short: no; you simply happen to be passing a value that *is* a
                              reference. Bass-by-reference (of a class) would be passing a reference/
                              pointer to something that *itself* happens to be a reference. In this
                              case, it is the address of the variable/field "x" that is actually
                              passed. In the original case, it is the current *value* of the
                              variable/field "x" that is passed - i.e. the reference to the
                              instance. The explanation works better with a picture, but...

                              I very-much doubt my voice will sway you much, but there we go...

                              Marc

                              Comment

                              Working...