#256 – Using Static Fields

Let’s say that we have both instance and static fields defined in a class:

        public string Name;

        public static string Creed;

This allows us read and write the Name property for each instance of the Dog class that we create.

            Dog kirby = new Dog();
            kirby.Name = "Kirby";

            Dog jack = new Dog();
            jack.Name = "Jack";

Notice that each instance of a Dog has its own copy of the Name field, since Name is an instance field.

We can also read/write the static Creed field, using the class name to qualify the field, rather than an instance variable.

            Dog.Creed = "Man's best friend";

There is only one copy of the Creed field, since Creed is a static field.

#255 – Static Fields vs. Instance Fields

When you declare a field in a class using the syntax below, you get an instance field, meaning that you’ll get one copy of the field’s data for each instance of the class that is created.  The field’s data is stored in the object (an instance of the class).

    public class Dog
    {
        public string Name;    // Instance field
    }

You can also define static fields in a class.  A static field is a variable where we can store a piece of data for the entire class, rather than a piece of data for each instance of the class.

You declare a static field using the static keyword.

    public class Dog
    {
        // Static field
        public static string Motto = "Man's best friend";
    }

With static fields, we always have exactly one copy of the field, no matter how many instances of the class we create.

#254 – Implementing a Read-Only Property with a Private Set Accessor

One way to implement a read-only property is to provide only a get accessor, letting the code internal to the class write the property’s value by writing directly to a private backing variable.

        private string personalHowl;
        public string PersonalHowl
        {
            get { return personalHowl; }
        }

However, it still might be helpful for code in the class to have a set accessor, which serves as a single place to execute whatever code is required when writing the property’s value.

You can use the private access modifier to make the set accessor available only to code within the class.  The property will appear to be read-only from code outside of the class.

        private string personalHowl;
        public string PersonalHowl
        {
            get { return personalHowl; }

            private set { personalHowl = value.ToUpper(); }
        }

#253 – Implementing a Read-Only Automatic Property

When using the automatic property syntax,C# requires that you define both a get and a set accessor.  But with the default syntax, you end up with a read/write property.

        public int Age { get; set;  }

But what if we want a read-only property, from the client code’s perspective?  Since we’re required to define the set accessor, it looks like client code would always be able to write to the property.

The solution is that we can add a private access modifier to the set accessor.

        public int Age { get; private set; }

With the set accessor private, code external to the class can read the property’s value, but not write to it.  But code within the class can still write to the property.

#252 – Automatic Properties

The typical syntax for a property implementation in C# is to define the public interface for the property and then have the implementation of the get and set accessors for the property read/write to a private backing variable.

        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

C# provides a shortcut for this structure through the use of automatic properties.  You can avoid declaring the private backing variable and implementing the get/set accessors by simply declaring the get/set accessors without a body.

        public string Name { get; set; }

When you declare a property this way, it appears exactly the same to any client code.  The underlying code generated by the compiler is also the same–a public property with a backing variable–but you don’t actually have access to the backing variable.

#251 – Class Properties Support the Principle of Encapsulation

Encapsulation is one of the core principles of object-oriented programming.  Encapsulation is the idea of hiding implementation details of a class from the users of that class and only exposing a public interface.

Class properties in C# support the idea of encapsulation.  Client code that wants to read or write a property has access only to its public interface–the data type of the property and the knowledge that there is a get or a set accessor (or both) for that property.

Client code that reads or writes a property has no information about:

  • How the class actually stores the property data
  • The implementation of the get accessor–how data is retrieved when a client reads the property value
  • The implementation of the set accessor–how data is stored when a client writes the property value

#250 – Using a set Accessor to Convert or Validate Property Data

We can use a property’s set accessor to do some validation on the new property value.  We may want to force the data to be within a particular range, do some conversion on the data, or throw an exception if an invalid value is specified.

Here’s an example where we use the set accessor of the Dog.Age property to enforce the constraint that a dog’s age can’t be less than 0.1.

        private float age;
        public float Age
        {
            get
            {
                return age;
            }
            set
            {
                // Enforce minimum age of 0.1
                age = (value < 0.1f) ? 0.1f : value;
            }
        }

Here’s another example, where we throw an exception if the user tries to set Name to an empty string.

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                if (value == "")
                    throw new Exception("Name can't be empty!");
                else
                    name = value;
            }
        }

#249 – Using a get Accessor to Clean up Property Data

It’s not always the case that when you read a property’s value, you want exactly the same value that you wrote to the property.

As an example, imagine that we have a Dog.ShowDogName property that lets us read/write our dog’s official “show dog” name.  Show dog names are titles, so each word should be capitalized.  For convenience, we’d like the client code to not worry about the capitalization, but have the class take care of it.

We store the property in its original non-capitalized state and then clean up the name by capitalizing it whenever the property is read.

        private string showDogName;
        public string ShowDogName
        {
            get
            {
                return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(showDogName);
            }

            set
            {
                showDogName = value;
            }
        }

Here’s an example of some client code using the new property:

            kirby.ShowDogName = "fitzgerald's rich socialite mister stinks-a-lot";

            // Fitzgerald's Rich Socialite Mister Stinks-A-Lot
            Console.WriteLine(kirby.ShowDogName);

#248 – Implementing a Property that Returns a Calculated Value

When implementing a property, you might sometimes want to define a property that returns a calculated value, rather than just returning the value of an internal field.

Below is an example.  We have a Dog class with Name and Age that each just wraps an internal field and are both read/write.  We also define an AgeInDogYears property, which is read-only and returns the dog’s age in dog years.

The Age property is defined to encapsulate a private age field.

        // Age in human years
        private int age;
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                age = value;
            }
        }

The AgeInDogYears property is read-only and returns the calculated dog-year age.

        // Age in dog years
        public float AgeInDogYears
        {
            get
            {
                float dogYearAge;

                if (age < 1)
                    dogYearAge = 0;
                else if (age == 1)
                    dogYearAge = 10.5f;
                else
                    dogYearAge = 21 + ((age - 2) * 4);

                return dogYearAge;
            }
        }

#247 – Implementing a Write-Only Property

You implement a write-only property in a class by implementing the set accessor, but not the get accessor.  This will allow client code to write the property’s value, but not read the current value.

Below is an example of a write-only property for the Dog class. The BarkPassword property can be written to, but not read back.  The class then uses the internal value of BarkPassword in the SecureBark method, to verify that the dog is allowed to bark.

        // Internal storage of secret name
        private string barkPassword;

        // Public property, write-only
        public string BarkPassword
        {
            set
            {
                barkPassword = value;
            }
        }

        // Bark method also sets lastBarked
        public void SecureBark(string password)
        {
            if (password == barkPassword)
                Console.WriteLine("{0}: Woof!", Name);
            else
                Console.WriteLine("Not allowed to bark");
        }

Here’s how we might use the new property:

            kirby.BarkPassword = "flotsam62!";

            kirby.SecureBark("notthepassword");