#790 – Property get and set Accessors Can Have Different Access Modifiers

When you implement a property in a class, you can specify different access modifiers for the get vs. set accessors.  This is true whether you are implementing the property yourself, or using an automatic property.

Different combinations of access modifiers include:

  • get/set both public – client can read/write property value
  • get/set both private – client has no access to the property
  • get public, set private – property is read-only
  • get private, set public – property is write-only
        // get/set both public
        public string Name { get; set; }

        // get/set both private
        private string SecretName { get; set; }

        // public get => read-only
        public string CalcName { get; private set; }

        // public set => write-only
        public string WriteOnlyName { private get; set; }
Advertisements

#789 – Grouping Constants into Their Own Class

Constants are declared as class members.  They are effectively static, since there is not a different value for each instance of the class, but you declare them without using the static keyword.

You can use a constant in the class in which it is defined, referring to it by name.  You can also use the constant in other classes, prefixing the name of the constant with the class name.

You can define a constant within a class that contains related data and methods.  It’s also a common practice to group a number of constants into their own class, which is used solely to contain a collection of constants.

    public class Constants
    {
        public const double Pi = 3.14159265358979;
        public const double GoldenRatio = 1.61803398874;
        public const string MNReply = "Not so bad";
    }

Now we can use the constants as follows:

            Console.WriteLine("Pi = {0}", Constants.Pi);

#788 – A Backing Field Stores Data for a Property

When you create a property, you’re creating a set of accessor methods to read and write the property’s value.  You also typically need a place to store the actual property value.

The data member where the property’s value is actually stored is known as a backing field, typically defined as a private field.

When you create an auto-implemented property, you don’t explicitly declare a backing field, but the compiler creates one for you in the IL that is generated.  Your code doesn’t have access to the field.

        // Backing field not declared, created automatically
        public int Age { get; set; }

If you create the property explicitly, then you’ll declare the backing field yourself.

        // Backing field
        private int age;

        // Property
        public int Age
        {
            get { return age; }
            set
            {
                if (value != age)
                    age = value;
            }
        }

#787 – Avoid Public Fields in a Class

When you declare a field in a class, you can set its accessibility to: public, private, protected, internal, or protected internal.

In general, you should declare fields as private or protected, instead of making them public.  For purposes of encapsulation, you typically expose public data members as properties, rather than fields.  This hides the implementation details of the data item from users of the class and makes it easier to change those details without changing or affecting code that uses the class.

Instead of this:

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

You should do this:

    public class Dog
    {
        // A property
        public string Name { get; set; }
    }

Or this:

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                // do other stuff
                name = value;
            }
        }

#786 – A Lazier Singleton Pattern

Ideally, you’d want the implementation of a singleton to be as “lazy” as possible, i.e.–create the instance as late as possible, just prior to when you need it.  This helps performance, since we only create the object if/when we need it.

In our earlier implementation, the instance of our class gets created whenever any of the static members of our class are accessed.  This might be when we first access the Instance property, but might be earlier, if we had other static members in the class.

Below is a Singleton pattern that is a bit lazier.

    public sealed class DogFactory
    {
        // Prevent instantiation
        private DogFactory() { }

        public static DogFactory Instance
        {
            get { return InstanceContainer.instance; }
        }

        private class InstanceContainer
        {
            // Prevent early instantiation due to beforefieldinit flag
            static InstanceContainer() { }

            internal static readonly DogFactory instance = new DogFactory();
        }
    }

#785 – The Singleton Pattern

Singleton is a design pattern that you can use when you have a situation where you want to limit a particular class to have at most one instance.

A singleton behaves similarly to a static class in C#, but has some advantages, in that it behaves as a traditional object.  (E.g. Can implement an interface, or be passed to a method).

Here’s a common (thread-safe) pattern for implementing a singleton in C#.

    public sealed class DogFactory
    {
        // Instance created when first referenced
        private static readonly DogFactory instance = new DogFactory();

        // Prevent early instantiation due to beforefieldinit flag
        static DogFactory() { }

        // Prevent instantiation
        private DogFactory() { }

        public static DogFactory Instance
        {
            get { return instance; }
        }

        // Actual methods go here, e.g.:
        public Dog CreateDog(string name)
        {
            return new Dog(name);
        }
    }

To use the singleton, you use the Instance property:

            Dog d = DogFactory.Instance.CreateDog("Bob");

#784 – When Not to Use a Static Class

You can create a static class as a container for a collection of static utility methods that you can invoke without having to create an instance of some object.

There are a few drawbacks to using static classes, however:

  • Global data and concurrency problems – static data within a static class is effectively global data, which can lead to concurrency problems when multiple threads access/change the static data
  • Allure of monolothic classes – it’s easy to end up with large static classes containing a bunch of unrelated methods
  • Can’t extend behavior of a static class – because you can’t inherit from a static class, you can’t extend the class’ behavior by using inheritance
  • Harder to isolate, for testing purposes – since we can’t treat the static class as an interface, we can’t swap out the actual implementation for a mocked version of the class