#1,218 – C# 6.0 – Using Expression-Bodied Property Getters

In addition to using expression-body definitions for method bodies in C# 6.0, you can use an expression-body definition to implement the getter of a read-only auto-property.

For example:

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

        public string BackwardsName => new string(Name.Reverse().ToArray());

The presence of the expression-body definition tells the compiler that this is a property with a getter, rather than a field.

Advertisement

#1,216 – C# 6.0 – Initializing Read-Only Auto-Properties from Constructors

In C# 6.0, when defining a read-only auto-property you can initialize the property as part of its declaration.

  public DateTime DogCreationTime { get; } = DateTime.Now;

You can also initialize these read-only auto-properties from a constructor.  For example:

    public class Dog
    {
        public string Name { get; }

        public Dog(string name)
        {
            Name = name;
        }
    }

#1,206 – C# 6.0 – Auto-Property Initializers

C# 3.0 introduced auto-implemented properties.

Older syntax:

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

Improved syntax, using auto-implemented properties:

public string Name { get; set; }

The new syntax provided no mechanism for specifying a default property value. To specify a default value, you either needed to go back to using an explicit backing variable or to set the default value from within a constructor.

C# 6.0 supports specifying default values for auto-implemented properties, as shown below.

        public string Name { get; set; } = "default";

#800 – A Property in an Interface May Include One or Two Accessors

Defining a property in an interface, you can define one or both of the property’s accessors.

    public interface IDogInfo
    {
        int CollarSize { get; set; }
        string Name { get; }
        string SecretName { set; }
    }

When you implement an interface, if a property in the interface has both accessors, you must implement both accessors, and both must be public (you set an access modifier of public on the entire property).

If a property in the interface includes only one accessor, you must implement that accessor, but you can optionally also implement the other accessor.

    public class Dog : IDogInfo
    {
        public int CollarSize { get; set; }

        // IDogInfo has just get
        public string Name
        {
            get { return "NotImpl"; }
        }

        // IDogInfo has just set, but we add a get
        public string SecretName { protected get; set; }
    }

#798 – You Can’t Override Accessors that Are Not Accessible

When you override a virtual property in a child class, you must replicate the accessibility of the accessors in the parent’s class.

However, if one of the accessors has been made inaccessible to the child class, you’ll be able to override the property itself, but not that accessor.

In the example below, we override the Description property, including the get accessor.  However, if we try to include the set accessor in the overridden property, we get a compile-time error because the set accessor is not accessible to the child class.

    public class Animal
    {
        protected string description;
        public virtual string Description
        {
            get { return string.Format("Animal: {0}",description); }

            private set
            {
                if (value != description)
                    description = value;
            }
        }
    }
    public class Dog : Animal
    {
        public override string Description
        {
            get { return string.Format("Dog: {0}", description); }

            private set
            {
                if (value != description)
                    description = value;
            }
        }
    }

798-001

#797 – Setting Accessibility for Property Accessors

By default, the accessibility of a property accessor matches the accessibility of the property itself.  You can also explicitly set the accessibility of an accessor, within certain limitations.

When setting the accessibility of a property accessor:

  • You can’t make an accessor more accessible than the property itself
  • You can’t specify the exact same accessibility on the accessor as the property
  • The property must have both get and set accessors defined
  • You can only set accessibility on one of the accessors, not both
  • You can’t set the accessibility of an accessor on a property in an interface
  • When overriding a virtual property in a parent class, you must replicate the accessibility of the accessors in the parent’s class exactly

The bottom line–you can make one of the accessors a bit more restrictive than the other.

        public string Name { get; protected set; }

#796 – Default Accessibility for Property Accessors

When you implement a property in a class, you define the property’s accessibility, e.g. public, private, protected, internal or protected internal.

Client code uses a property like a field, reading and writing the property’s value.  The property is actually implemented as a two accessor methods.  The get accessor is called when some code reads the property’s value and the set accessor is called when some code write’s the property’s value.

By default, the accessibility of the two property accessors matches the accessibility of the property itself.

        // Property is public, so both get and set accessors are public
        public string Name { get; set; }

        // Property is private, so both get and set accesors are private
        private string SecreteName { get; set; }

#793 – Being Notified When an Object’s Properties Change, Part II

Once you’ve implemented the INotifyPropertyChanged interface in a class, you can subscribe to the PropertyChanged event for an instance of your class.  Assuming that you’ve implemented INotifyPropertyChanged properly, the event will fire whenever any property value in the object changes.

The code below assumes that the Dog class implements INotifyPropertyChanged.

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

            d.PropertyChanged += d_PropertyChanged;

            d.Name = "Bob Jr.";
            d.AgeThisDog();
            d.Age = 10;
        }

        static void d_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            Console.WriteLine(string.Format("Property {0} just changed", e.PropertyName));
        }

793-001

The PropertyChanged event handler receives an instance of a PropertyChangedEventArgs object, which just contains a PropertyName property that tells you which property changed.  It pass any information about either the old or the new values of the property.  The assumption is that client code can read the updated property value on their own.

#792 – Being Notified When an Object’s Properties Change, Part I

If you write a class, there’s a pattern that you can implement, to let users of your class know when a property value changes.  This pattern is implemented by implementing the INotifyPropertyChanged in your class.

The purpose of this pattern is to let client code know that some property value has changed, in situations where that code didn’t initiate the change.  For example, this pattern is used in data binding.

Below is an example of a class that implements INotifyPropertyChanged.  The class defines an event that is fired whenever any property value changes.

    public class Dog : INotifyPropertyChanged
    {
        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                if (name != value)
                {
                    name = value;
                    RaisePropertyChanged("Name");
                }
            }
        }

        private int age;
        public int Age
        {
            get { return age; }
            set
            {
                if (age != value)
                {
                    age = value;
                    RaisePropertyChanged("Age");
                }
            }
        }

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

        public void AgeThisDog()
        {
            Age++;
        }

        //-- INotifyPropertyChanged implementation

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string prop)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

Part II of this topic will show how client code can use this new event.

#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