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. .NET (Core and Framework)
  4. Good practice or not? Defaulting member variables via properties

Good practice or not? Defaulting member variables via properties

Scheduled Pinned Locked Moved .NET (Core and Framework)
questiontutorial
9 Posts 3 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.
  • A Offline
    A Offline
    AEternal
    wrote on last edited by
    #1

    I've been wrestling with the idea of defaulting member variables, not necessarily in the constructor, but in their accessor properties. For example:

    private string _name;
    
    public string Name
    {
        get
        {
            if (this._name == null) this._name = String.Empty;
            return this._name;
        }
        set { this._name = value; }
    }
    

    This way, I know that, no matter what, whenever I access MyObject.Name, I'll be getting a valid string object and never a null, so that when I go to do MyObject.Name.Trim(), I'll never get a null object exception. This saves me time and lines of code in my application. My question is, is this good practice? Is it better to let the exception occur and check for null elsewhere?

    S 1 Reply Last reply
    0
    • A AEternal

      I've been wrestling with the idea of defaulting member variables, not necessarily in the constructor, but in their accessor properties. For example:

      private string _name;
      
      public string Name
      {
          get
          {
              if (this._name == null) this._name = String.Empty;
              return this._name;
          }
          set { this._name = value; }
      }
      

      This way, I know that, no matter what, whenever I access MyObject.Name, I'll be getting a valid string object and never a null, so that when I go to do MyObject.Name.Trim(), I'll never get a null object exception. This saves me time and lines of code in my application. My question is, is this good practice? Is it better to let the exception occur and check for null elsewhere?

      S Offline
      S Offline
      Scott Dorman
      wrote on last edited by
      #2

      I think generally you want to avoid get accessors that have a "side effect" like this. The better way would be to ensure that the variable is set to the appropriate default in the constructor (or when it is declared) and then restrict the allowable values in the set accessor. For your example, it would look something like this:

      private string _name;

      public string Name
      {
      get
      {
      return this._name;
      }
      set
      {
      // Take your choice here. If you want to prevent nulls and
      // throw an exception use this:
      if (value == null)
      {
      throw new ArgumentNullException("value");
      }

         // otherwise, if you just want to prevent nulls you
         // could use this:
         if (value == null)
         {
            value = String.Emtpy;
         }
       
         if (String.Compare(this.\_name, value, StringComparison.InvariantCultureIgnoreCase) != 0)
         {
            this.\_name = value; 
         }
      }
      

      }

      The call to String.Compare isn't required but it prevents the backing variable from being changed unnecessarily.

      ----------------------------- In just two days, tomorrow will be yesterday.

      A 1 Reply Last reply
      0
      • S Scott Dorman

        I think generally you want to avoid get accessors that have a "side effect" like this. The better way would be to ensure that the variable is set to the appropriate default in the constructor (or when it is declared) and then restrict the allowable values in the set accessor. For your example, it would look something like this:

        private string _name;

        public string Name
        {
        get
        {
        return this._name;
        }
        set
        {
        // Take your choice here. If you want to prevent nulls and
        // throw an exception use this:
        if (value == null)
        {
        throw new ArgumentNullException("value");
        }

           // otherwise, if you just want to prevent nulls you
           // could use this:
           if (value == null)
           {
              value = String.Emtpy;
           }
         
           if (String.Compare(this.\_name, value, StringComparison.InvariantCultureIgnoreCase) != 0)
           {
              this.\_name = value; 
           }
        }
        

        }

        The call to String.Compare isn't required but it prevents the backing variable from being changed unnecessarily.

        ----------------------------- In just two days, tomorrow will be yesterday.

        A Offline
        A Offline
        AEternal
        wrote on last edited by
        #3

        So in this example, what is use of preventing assignment of the member object to null? I'd still have to be prepared for null values to come back from the Name property, so if I'm prepared for that in my code, why would I then prevent the ability to set it to null? Though it seems like your example now tells the user that there was an attempt to write to the member object at some point because it is no longer null, whereas in mine, you never know if anyone tried to set it.

        S 1 Reply Last reply
        0
        • A AEternal

          So in this example, what is use of preventing assignment of the member object to null? I'd still have to be prepared for null values to come back from the Name property, so if I'm prepared for that in my code, why would I then prevent the ability to set it to null? Though it seems like your example now tells the user that there was an attempt to write to the member object at some point because it is no longer null, whereas in mine, you never know if anyone tried to set it.

          S Offline
          S Offline
          Scott Dorman
          wrote on last edited by
          #4

          The example I provided assumes that _name has already been set to it's default value (presumably of String.Empty) in the constructor. With the variable already having it's default value and restricting it from being set to null in the set accessor, you should never return a null value from the get accessor.

          ----------------------------- In just two days, tomorrow will be yesterday.

          A 1 Reply Last reply
          0
          • S Scott Dorman

            The example I provided assumes that _name has already been set to it's default value (presumably of String.Empty) in the constructor. With the variable already having it's default value and restricting it from being set to null in the set accessor, you should never return a null value from the get accessor.

            ----------------------------- In just two days, tomorrow will be yesterday.

            A Offline
            A Offline
            AEternal
            wrote on last edited by
            #5

            That makes sense, and I appreciate your taking the time to answer, Scott. :) This seems functionally equivalent to what I described, which is great, but I'm quite not certain what this method buys me. Predictability? What is your reasoning for doing this? I really want to understand.

            S 1 Reply Last reply
            0
            • A AEternal

              That makes sense, and I appreciate your taking the time to answer, Scott. :) This seems functionally equivalent to what I described, which is great, but I'm quite not certain what this method buys me. Predictability? What is your reasoning for doing this? I really want to understand.

              S Offline
              S Offline
              Scott Dorman
              wrote on last edited by
              #6

              No problem. I'm glad I was able to clarify the example. It is very similar functionaly to your original example. The benefit here is that you guarantee that accessing a property does not change the internal state of your object, generally termed a "side effect". In your example, the internal state could possibly change when the property is accessed. In order to achieve your result of guaranteeing that the property is not null when it is accessed, the backing variable should be set to some appropriate default (in this case, String.Emtpy) as early as possible and then the property should prevent someone from explicitly setting it to null. The choice is yours to decide how to restrict setting it to null and depends on your desired behavior. I have written properties using both methods and they both have their place, you just need to decide which is appropriate for your context. A lot of properties (particularly in the CLR itself) raise property change events when the value of the property changes. These events are not "smart" so they are always raised. The call to the String.Compare method prevents the property from being set to the same value it currently holds, which prevents the property change events from being raised.

              ----------------------------- In just two days, tomorrow will be yesterday.

              A 1 Reply Last reply
              0
              • S Scott Dorman

                No problem. I'm glad I was able to clarify the example. It is very similar functionaly to your original example. The benefit here is that you guarantee that accessing a property does not change the internal state of your object, generally termed a "side effect". In your example, the internal state could possibly change when the property is accessed. In order to achieve your result of guaranteeing that the property is not null when it is accessed, the backing variable should be set to some appropriate default (in this case, String.Emtpy) as early as possible and then the property should prevent someone from explicitly setting it to null. The choice is yours to decide how to restrict setting it to null and depends on your desired behavior. I have written properties using both methods and they both have their place, you just need to decide which is appropriate for your context. A lot of properties (particularly in the CLR itself) raise property change events when the value of the property changes. These events are not "smart" so they are always raised. The call to the String.Compare method prevents the property from being set to the same value it currently holds, which prevents the property change events from being raised.

                ----------------------------- In just two days, tomorrow will be yesterday.

                A Offline
                A Offline
                AEternal
                wrote on last edited by
                #7

                I do understand it now. From a functional perspective, they're no different, but from a conceptual and practice perspective, it keeps the acts of Setting and Getting separate from one another. Thanks again, Scott. :)

                S N 2 Replies Last reply
                0
                • A AEternal

                  I do understand it now. From a functional perspective, they're no different, but from a conceptual and practice perspective, it keeps the acts of Setting and Getting separate from one another. Thanks again, Scott. :)

                  S Offline
                  S Offline
                  Scott Dorman
                  wrote on last edited by
                  #8

                  Glad to help.

                  ----------------------------- In just two days, tomorrow will be yesterday.

                  1 Reply Last reply
                  0
                  • A AEternal

                    I do understand it now. From a functional perspective, they're no different, but from a conceptual and practice perspective, it keeps the acts of Setting and Getting separate from one another. Thanks again, Scott. :)

                    N Offline
                    N Offline
                    Not Active
                    wrote on last edited by
                    #9

                    Another point to add. Your original method, initializing the member field to a valid value when accessed, is a technique called "lazy initialization" and is good for initializing objects that may have a heavy penalty such as in time or memory usage. For example, if your object contains a large collection that is not used in say 50% of the cases, you can put off initialization until it is needed. Or if that collection may take time to initialze, may be populated from a database, you can put it off until after the object has been created.


                    only two letters away from being an asset

                    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