Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Finally! I found a valid use for the ref keyword

Finally! I found a valid use for the ref keyword

Scheduled Pinned Locked Moved C#
questioncsharpdata-structuresbeta-testingxml
16 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    Foothill
    wrote on last edited by
    #1

    Not really a question but I would like some feedback. I have been programming in C# for years now and until today I never could find a way to use the ref keyword in a syntax-correct way. I'm writing code to build XML based on data classes for what must be the thousandth time. The simplest way to generate the data is in plain old strings but I needed a fast way to check for reserved XML characters and update the string only if necessary. Strings are immutable and I don't want to have to copy the string if necessary as this just adds overhead so I came up with this:

    public static bool ContainsReservedXmlCharacters(string value)
    {
    // This array can be stored in a static class so it's only created once
    char[] reservedCharacters = new char[] { '<', '>', '&', '%' };

    for (int i = 0; i < value.Length; ++i)
    {
    if (Array.Exists(reservedCharacters, delegate (char c) { return c.Equals(value[i]); }))
    return true;
    }

    return false;
    }

    public static void ValidateForXml(ref string value)
    {
    if (ContainsReservedXmlCharacters(value))
    {
    value = String.Format("<![CDATA[{0}]]>", value);
    }
    }

    This way, I can check the string if contains characters that it shouldn't and only replace the string if necessary. Experience has taught that reserved characters do sneak into XML from time to time but not that often. This should save some parsing time as the string is copied infrequently. I could even write the function to escape the reserved characters if needed. If there is still a use for ref, it is with handling immutable types such as strings in functions where they may or may not be replaced with a new value. What does the community think about this?

    if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

    Richard DeemingR B L B 4 Replies Last reply
    0
    • F Foothill

      Not really a question but I would like some feedback. I have been programming in C# for years now and until today I never could find a way to use the ref keyword in a syntax-correct way. I'm writing code to build XML based on data classes for what must be the thousandth time. The simplest way to generate the data is in plain old strings but I needed a fast way to check for reserved XML characters and update the string only if necessary. Strings are immutable and I don't want to have to copy the string if necessary as this just adds overhead so I came up with this:

      public static bool ContainsReservedXmlCharacters(string value)
      {
      // This array can be stored in a static class so it's only created once
      char[] reservedCharacters = new char[] { '<', '>', '&', '%' };

      for (int i = 0; i < value.Length; ++i)
      {
      if (Array.Exists(reservedCharacters, delegate (char c) { return c.Equals(value[i]); }))
      return true;
      }

      return false;
      }

      public static void ValidateForXml(ref string value)
      {
      if (ContainsReservedXmlCharacters(value))
      {
      value = String.Format("<![CDATA[{0}]]>", value);
      }
      }

      This way, I can check the string if contains characters that it shouldn't and only replace the string if necessary. Experience has taught that reserved characters do sneak into XML from time to time but not that often. This should save some parsing time as the string is copied infrequently. I could even write the function to escape the reserved characters if needed. If there is still a use for ref, it is with handling immutable types such as strings in functions where they may or may not be replaced with a new value. What does the community think about this?

      if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #2

      Foothill wrote:

      What does the community think about this?

      I think you should be using System.Xml.Linq[^] to build your XML documents. :) If you build your own XML generator, you're bound to run into edge cases that you hadn't considered. For example, if your input contains "Test]]>", your "valid" string will contain "<![CDATA[Test]]>]]>", which is not valid XML. Using XLinq:

      new XCData("Test]]>")

      gives:

      <![CDATA[Test]]]]><![CDATA[>]]>

      which looks odd, but is valid.


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      F 1 Reply Last reply
      0
      • F Foothill

        Not really a question but I would like some feedback. I have been programming in C# for years now and until today I never could find a way to use the ref keyword in a syntax-correct way. I'm writing code to build XML based on data classes for what must be the thousandth time. The simplest way to generate the data is in plain old strings but I needed a fast way to check for reserved XML characters and update the string only if necessary. Strings are immutable and I don't want to have to copy the string if necessary as this just adds overhead so I came up with this:

        public static bool ContainsReservedXmlCharacters(string value)
        {
        // This array can be stored in a static class so it's only created once
        char[] reservedCharacters = new char[] { '<', '>', '&', '%' };

        for (int i = 0; i < value.Length; ++i)
        {
        if (Array.Exists(reservedCharacters, delegate (char c) { return c.Equals(value[i]); }))
        return true;
        }

        return false;
        }

        public static void ValidateForXml(ref string value)
        {
        if (ContainsReservedXmlCharacters(value))
        {
        value = String.Format("<![CDATA[{0}]]>", value);
        }
        }

        This way, I can check the string if contains characters that it shouldn't and only replace the string if necessary. Experience has taught that reserved characters do sneak into XML from time to time but not that often. This should save some parsing time as the string is copied infrequently. I could even write the function to escape the reserved characters if needed. If there is still a use for ref, it is with handling immutable types such as strings in functions where they may or may not be replaced with a new value. What does the community think about this?

        if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

        B Offline
        B Offline
        Bohdan Stupak
        wrote on last edited by
        #3

        I agree with the previous commentator that for this specific case System.Xml.Linq is the best tried and true solution. However, if we take a look at the broader case

        Quote:

        If there is still a use for ref, it is with handling immutable types such as strings in functions where they may or may not be replaced with a new value.

        then how about working with mutable type instead of immutable? i.e. StringBuilder[^]

        F 1 Reply Last reply
        0
        • Richard DeemingR Richard Deeming

          Foothill wrote:

          What does the community think about this?

          I think you should be using System.Xml.Linq[^] to build your XML documents. :) If you build your own XML generator, you're bound to run into edge cases that you hadn't considered. For example, if your input contains "Test]]>", your "valid" string will contain "<![CDATA[Test]]>]]>", which is not valid XML. Using XLinq:

          new XCData("Test]]>")

          gives:

          <![CDATA[Test]]]]><![CDATA[>]]>

          which looks odd, but is valid.


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          F Offline
          F Offline
          Foothill
          wrote on last edited by
          #4

          At some point, once my understanding of XML is good enough that is, I can take off the training wheels and move over to Linq XML. I would like to gain a deeper knowledge of XML and how to manipulate it first before I do. Still, I was so surprised that I found a use for the ref keyword that I had to share.

          if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

          L 1 Reply Last reply
          0
          • F Foothill

            At some point, once my understanding of XML is good enough that is, I can take off the training wheels and move over to Linq XML. I would like to gain a deeper knowledge of XML and how to manipulate it first before I do. Still, I was so surprised that I found a use for the ref keyword that I had to share.

            if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            The framework will not make a copy of the string when entering a new method; it is not a value-type, so no copy. It will create a new immutable once you manipulate it.

            Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

            F 1 Reply Last reply
            0
            • B Bohdan Stupak

              I agree with the previous commentator that for this specific case System.Xml.Linq is the best tried and true solution. However, if we take a look at the broader case

              Quote:

              If there is still a use for ref, it is with handling immutable types such as strings in functions where they may or may not be replaced with a new value.

              then how about working with mutable type instead of immutable? i.e. StringBuilder[^]

              F Offline
              F Offline
              Foothill
              wrote on last edited by
              #6

              Since I was building this to process inputs from users into an XML document and the statistically low incidence of invalid characters, StringBuilder was not the best option in this case. The data exists as a bunch of strings already and copying them all to a StringBuilder on the off chance they will be changed seemed wasteful. I wanted to combine the validation and replacement operations into a single step but without the need to create copies of a string in memory unnecessarily. The code itself is run-of-the-mill. I was just surprised to actually find a language-correct appllicaton for ref as I have never been able to put it to use before.

              if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

              1 Reply Last reply
              0
              • L Lost User

                The framework will not make a copy of the string when entering a new method; it is not a value-type, so no copy. It will create a new immutable once you manipulate it.

                Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                F Offline
                F Offline
                Foothill
                wrote on last edited by
                #7

                That's news to me. Do you happen to have a reference to that? I was operating on the assumption that immutable types are passed by copy and not by pointer, hence the need for ref so that it could be passed by pointer and replaced if necessary.

                if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

                L 2 Replies Last reply
                0
                • F Foothill

                  That's news to me. Do you happen to have a reference to that? I was operating on the assumption that immutable types are passed by copy and not by pointer, hence the need for ref so that it could be passed by pointer and replaced if necessary.

                  if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  I'll be googling for a reference after the groceries; I'm out of coffee and that's a priority. I vaguely remember something about string.Clone that doesn't return a clone, because it is "immutable" and the string will only exist in memory once.

                  Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                  1 Reply Last reply
                  0
                  • F Foothill

                    That's news to me. Do you happen to have a reference to that? I was operating on the assumption that immutable types are passed by copy and not by pointer, hence the need for ref so that it could be passed by pointer and replaced if necessary.

                    if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

                    L Offline
                    L Offline
                    Lost User
                    wrote on last edited by
                    #9

                    Coffee works miracles. Only "interned" strings are kept in memory in that way, and if your string doesn't come from a literal but from user-input, this doesn't happen automatic. The string is still a reference-type, and its value 'should' not be duplicated as with a value-type. Passing it with the ref keyword means that you are modifying the data of supplied variable. Since the alternative does return a new immutable string, what you said makes sense :thumbsup:

                    Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                    1 Reply Last reply
                    0
                    • F Foothill

                      Not really a question but I would like some feedback. I have been programming in C# for years now and until today I never could find a way to use the ref keyword in a syntax-correct way. I'm writing code to build XML based on data classes for what must be the thousandth time. The simplest way to generate the data is in plain old strings but I needed a fast way to check for reserved XML characters and update the string only if necessary. Strings are immutable and I don't want to have to copy the string if necessary as this just adds overhead so I came up with this:

                      public static bool ContainsReservedXmlCharacters(string value)
                      {
                      // This array can be stored in a static class so it's only created once
                      char[] reservedCharacters = new char[] { '<', '>', '&', '%' };

                      for (int i = 0; i < value.Length; ++i)
                      {
                      if (Array.Exists(reservedCharacters, delegate (char c) { return c.Equals(value[i]); }))
                      return true;
                      }

                      return false;
                      }

                      public static void ValidateForXml(ref string value)
                      {
                      if (ContainsReservedXmlCharacters(value))
                      {
                      value = String.Format("<![CDATA[{0}]]>", value);
                      }
                      }

                      This way, I can check the string if contains characters that it shouldn't and only replace the string if necessary. Experience has taught that reserved characters do sneak into XML from time to time but not that often. This should save some parsing time as the string is copied infrequently. I could even write the function to escape the reserved characters if needed. If there is still a use for ref, it is with handling immutable types such as strings in functions where they may or may not be replaced with a new value. What does the community think about this?

                      if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #10

                      Perhaps "ref" has more of a place when it comes to "inter-op". It seems there is frequent use "ref" in C# when talking to MS Word, for example:

                              Globals.ThisDocument.CheckSpelling(
                                  ref missing, ref ignoreUppercase, ref missing, ref missing, ref missing, ref missing,
                                  ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                      

                      "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

                      Richard DeemingR F 2 Replies Last reply
                      0
                      • L Lost User

                        Perhaps "ref" has more of a place when it comes to "inter-op". It seems there is frequent use "ref" in C# when talking to MS Word, for example:

                                Globals.ThisDocument.CheckSpelling(
                                    ref missing, ref ignoreUppercase, ref missing, ref missing, ref missing, ref missing,
                                    ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                        

                        "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

                        Richard DeemingR Offline
                        Richard DeemingR Offline
                        Richard Deeming
                        wrote on last edited by
                        #11

                        That's not so much of an issue since C# 4 was released. You can omit all of the ref missing arguments, and use named arguments for the ones you want to pass. And I believe you may be able to omit the ref on the other arguments as well (for Interop calls only); but don't quote me on that. :)


                        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                        "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                        1 Reply Last reply
                        0
                        • L Lost User

                          Perhaps "ref" has more of a place when it comes to "inter-op". It seems there is frequent use "ref" in C# when talking to MS Word, for example:

                                  Globals.ThisDocument.CheckSpelling(
                                      ref missing, ref ignoreUppercase, ref missing, ref missing, ref missing, ref missing,
                                      ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                          

                          "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

                          F Offline
                          F Offline
                          Foothill
                          wrote on last edited by
                          #12

                          That also makes sense. The MS documentation on ref is a little confusing since technically all objects are passed by reference (i.e. pointer). Since C# does everything it can to hide all the pointer shenanigans, I do believe it was tacked on to show that a method argument is being passed by pointer and highlight that the pointer passed to the method might not point to the same location when the function exits. Passing pointers around in C++ is common and I believe this was their way of representing it.

                          if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

                          L Richard DeemingR 2 Replies Last reply
                          0
                          • F Foothill

                            That also makes sense. The MS documentation on ref is a little confusing since technically all objects are passed by reference (i.e. pointer). Since C# does everything it can to hide all the pointer shenanigans, I do believe it was tacked on to show that a method argument is being passed by pointer and highlight that the pointer passed to the method might not point to the same location when the function exits. Passing pointers around in C++ is common and I believe this was their way of representing it.

                            if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

                            L Offline
                            L Offline
                            Lost User
                            wrote on last edited by
                            #13

                            The short answer is: "value types" (like int) are passed as / by "value". In order to "update the source", you need to pass them "by reference" via the "ref" keyword. Another example is the "Interlocked" commands; which allow you to update "value type refs" (e.g. "counters") concurrently from multiple threads as atomic operations.

                            "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

                            1 Reply Last reply
                            0
                            • F Foothill

                              That also makes sense. The MS documentation on ref is a little confusing since technically all objects are passed by reference (i.e. pointer). Since C# does everything it can to hide all the pointer shenanigans, I do believe it was tacked on to show that a method argument is being passed by pointer and highlight that the pointer passed to the method might not point to the same location when the function exits. Passing pointers around in C++ is common and I believe this was their way of representing it.

                              if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

                              Richard DeemingR Offline
                              Richard DeemingR Offline
                              Richard Deeming
                              wrote on last edited by
                              #14

                              Foothill wrote:

                              all objects are passed by reference

                              Slightly confusing two different things. Reference types are passed as references (pointers), but they are not passed "by ref". You can update things in the reference that the parameter points to; but if you change the parameter to point to a different reference, that change won't be seen by the caller. Adding ref (or out) to the parameter means that, if you change it to point to something else, that change will be seen by the caller. My C++ is terribly rusty, but I believe it's equivalent to passing either a * (by value) or a ** (by ref) parameter.


                              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                              "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                              P 1 Reply Last reply
                              0
                              • Richard DeemingR Richard Deeming

                                Foothill wrote:

                                all objects are passed by reference

                                Slightly confusing two different things. Reference types are passed as references (pointers), but they are not passed "by ref". You can update things in the reference that the parameter points to; but if you change the parameter to point to a different reference, that change won't be seen by the caller. Adding ref (or out) to the parameter means that, if you change it to point to something else, that change will be seen by the caller. My C++ is terribly rusty, but I believe it's equivalent to passing either a * (by value) or a ** (by ref) parameter.


                                "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                                P Offline
                                P Offline
                                phil o
                                wrote on last edited by
                                #15

                                Richard Deeming wrote:

                                I believe it's equivalent to passing either a * (by value) or a ** (by ref) parameter.

                                I don't really see it like that, but I may be wrong. I see a pointer as a inherent array of values whose type is this of the pointer (a char* as an array of characters, for example). I see a pointer to a pointer as a bidimensional array (a char** as an array of arrays of characters). I like the possibility in C++ to specify the const-ness of either the value pointed to, or the const-ness of the pointer itself.

                                void func(const object* obj)

                                allows to change the address to which obj is pointing, but not the value of the eventual members which obj could have.

                                void func(object* const obj)

                                forbids to change the address to which obj is pointing, but allows to change the values of its eventual members.

                                void func(const object* const obj)

                                forbids to change the address to which obj is pointing as well as any modification to object members. In that sense, C++ is more versatile as it allows to control very precisely the mutability of the objects we are using. In C#, controlling the mutability of an object implies a lot more code and complexity. Again, I am quite fresh in C++, so I may be wrong, or incomplete on the subject.

                                "I'm neither for nor against, on the contrary." John Middle

                                1 Reply Last reply
                                0
                                • F Foothill

                                  Not really a question but I would like some feedback. I have been programming in C# for years now and until today I never could find a way to use the ref keyword in a syntax-correct way. I'm writing code to build XML based on data classes for what must be the thousandth time. The simplest way to generate the data is in plain old strings but I needed a fast way to check for reserved XML characters and update the string only if necessary. Strings are immutable and I don't want to have to copy the string if necessary as this just adds overhead so I came up with this:

                                  public static bool ContainsReservedXmlCharacters(string value)
                                  {
                                  // This array can be stored in a static class so it's only created once
                                  char[] reservedCharacters = new char[] { '<', '>', '&', '%' };

                                  for (int i = 0; i < value.Length; ++i)
                                  {
                                  if (Array.Exists(reservedCharacters, delegate (char c) { return c.Equals(value[i]); }))
                                  return true;
                                  }

                                  return false;
                                  }

                                  public static void ValidateForXml(ref string value)
                                  {
                                  if (ContainsReservedXmlCharacters(value))
                                  {
                                  value = String.Format("<![CDATA[{0}]]>", value);
                                  }
                                  }

                                  This way, I can check the string if contains characters that it shouldn't and only replace the string if necessary. Experience has taught that reserved characters do sneak into XML from time to time but not that often. This should save some parsing time as the string is copied infrequently. I could even write the function to escape the reserved characters if needed. If there is still a use for ref, it is with handling immutable types such as strings in functions where they may or may not be replaced with a new value. What does the community think about this?

                                  if (Object.DividedByZero == true) { Universe.Implode(); } Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016

                                  B Offline
                                  B Offline
                                  Bernhard Hiller
                                  wrote on last edited by
                                  #16

                                  void ValidateForXml(ref string value)... I do not like the idea so much, though it is syntactically correct. That function is meant to encode some data, so I'd declare it accordingly, i.e. with a return type: string EncodeForXml(string input): now its purpose is clear. By the way, I'd look for some library for that purpose instead of trying to invent my own library - are you sure can enumerate all the special cases you have to take care of when doing it your self?

                                  Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!

                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  • Login

                                  • Don't have an account? Register

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • World
                                  • Users
                                  • Groups