#1, 023 – Fields Are Initialized Before Execution of Constructors

When you declare a field in a class and initialize the field when it is declared, the initialization of the field will happen when an instance of the class is created, but before the constructor is invoked.  All fields are initialized before the constructor executes, in the order in which they are declared.

Assume that we have a Dog class defined as follows:

    public class Dog
    {
        public string Sound = "Woof";
        public Cat Friend = new Cat("Garfield");
        public string Name { get; set; }

        public Dog(string name)
        {
            Console.WriteLine("Dog constructor for {0}, Sound is {1}", name, Sound);
            Name = name;
        }
    }

When we create an instance of a Dog, the Sound and Friend fields are initialized before the Dog constructor is invoked.

            Dog d = new Dog("Kirby");

1023-001

Advertisement

#791 – Properties Are Not Variables

A property cannot be used in the same way as a variable, like a field can.

A field is a variable that is defined within a class and it denotes an actual storage location.  Because it refers to a storage location, you can pass a field by reference, using a ref or out keyword on the argument.

If Name is a public field of a Dog class, you can do this:

        static void Main(string[] args)
        {
            Dog d = new Dog("Bob");

            MakeNoble(ref d.Name);
        }

        private static void MakeNoble(ref string name)
        {
            name = "Sir " + name;
        }

A property, on the other hand, is not a variable and its name does not refer directly to a storage location.  So you can’t pass a property as a ref or out argument to a method.

            Dog d = new Dog("Bob");
            d.Age = 5;
            AgeMe(ref d.Age);  // Compile-time Error

#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;
            }
        }

#669 – Initializing Fields by Calling A Method

You can initialize fields in a class at the point where you declare them, using a constant.  You can also initialize a field to a value returned from a call to a method–as long as the method is not an instance method within the same class.

Here’s an example, where we call a static method in the same class to initialize a field.

    public class Dog
    {
        private static string GenerateCreationInfo()
        {
            return string.Format("I was created at {0}", DateTime.Now);
        }

        public string CreationInfo = GenerateCreationInfo();

        public string Name { get; set; }
        public int Age { get; set; }

        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }
    }

#602 – Initializing Fields in a Class

You can initialize instance-level fields in a class when you declare them.  If you do not initialize them, all fields are initialized to default values (0 for numeric types, null for reference types).

In the fragment of the Dog class below, we initialize two instance-level fields and one static field.

    public class Dog
    {
        // Instance fields
        public string Name = "Bowser";
        public int Age = 1;

        // Static fields (one for entire type, rather than 1/instance)
        public static string CanineMotto = "We're here to serve you";

        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }

        public Dog() { }
    }
            Dog myDog = new Dog();
            Console.WriteLine("My dog {0} is aged {1}", myDog.Name, myDog.Age);

            Dog yourDog = new Dog("Kirby", 15);
            Console.WriteLine("Your dog {0} is aged {1}", yourDog.Name, yourDog.Age);

            Console.WriteLine("Dog motto: {0}", Dog.CanineMotto);

#443 – An Interface Cannot Contain Fields

An interface can contain methods, properties, events or indexers.  It cannot contain fields.

    interface IMoo
    {
        // Methods
        void Moo();

        // Field not allowed - compile-time error
        string Name;

Instead of a field, you can use a property.

    interface IMoo
    {
        // Methods
        void Moo();

        // Name as a property is OK
        string Name { get; set; }

Interfaces don’t allow fields because they consist of a contract that is a list of methods, whose implementation is provided by a class. Properties are implemented as methods (get and set accessors), so they fit this model.  But fields are just data locations, so it doesn’t make sense to include them in an interface.

#336 – Declaring and Using a readonly Field

You can make a field in a class read-only by using the readonly modifier when the field is declared.

In the example below, code that creates or uses instances of the Dog class will be able to read the SerialNumber field, but not write to it.

    public class Dog
    {
        public string Name;
        public int Age;
        public readonly string SerialNumber;

        public Dog(string name, int age, string serNumber)
        {
            Name = name;
            Age = age;
            SerialNumber = serNumber;
        }
    }

You can assign a value to a readonly field in only two different places:

  • In the class’ constructor
  • As part of the field’s declaration
        public readonly string BestFriend = "Man";

#310 – Accessibility of Fields in a Class

You can apply access modifiers to fields defined in a class to define their accessibility.  Accessibility dictates what other code is allowed to read and the write the value of a field.

  • public – All code can read/write the field
  • private – Only code in the defining class can read/write the field
  • protected – Code in the defining class or derived classes can read/write the field
  • internal – All code in the defining assembly can read/write the field
  • protected internal – Code in the defining assembly or in derived classes can read/write the field
    public class Dog
    {
        // All code can access
        public string Nickname;

        // Only code in this class can access
        private string genericDogSecretName;

        // Code in this class or subclass can access
        protected int totalBarkCount;

        // Code in same assembly can access
        internal int invokeCount;

        // Code in same assembly or derived classes can access
        protected internal int barkInvokeCount;
    }

#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.