#799 – Interface Members Are Implicitly Public

When you declare an interface, you cannot use access modifiers on interface’s member.  An interface makes a collection of members available to code that accesses a class implementing that interface.  So it makes sense that the interface members are public.

    public interface IBark
    {
        int BarkCount { get; set; }
        void Bark(string woofSound, int count);
    }

When you implement an interface, you must mark the interface members as public.

    public class Dog : IBark
    {
        public int BarkCount { get; set; }

        public void Bark(string woofSound, int count)
        {
            for (int i = 1; i <= count; i++)
                Console.WriteLine(woofSound);
        }
    }

If you implement the interface explicitly, the members are implicitly public and you cannot mark them with access modifiers.

        int IBark.BarkCount { get; set; }

        void IBark.Bark(string woofSound, int count)
        {
            for (int i = 1; i <= count; i++)
                Console.WriteLine(woofSound);
        }

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

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

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

#717 – Class Members Can’t Be More Accessible Than Their Type

When specifying the accessibility for a class member, the member’s type must be at least as accessible as the member itself.  For methods, the return type and types of all parameters must be as accessible as the method.

This makes sense–client code can’t access a class member if it can’t access that member’s type.  Client code also can’t invoke a method if it can’t access the type of all the method’s parameters and return type.

In the example below, because the DogCollar type is internal, the Collar property must be internal or private.

    internal class DogCollar
    {
        public string Material { get; set; }
        public double Size { get; set; }
    }

    public class Dog
    {
        public string Name { get; set; }

        // Error: DogCollar less accessible (internal) than Collar (public)
        public DogCollar Collar { get; set; }

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

#714 – Accessibility of a Public Method in an Internal Type

When you declare a class with an accessibility of internal, the class is usable only from code within the same assembly.  If this class then contains a member whose accessibility is public, that member is still limited to an accessibility level of internal.  A member of a class cannot be more accessible than the class itself.

This makes sense.  If we have code that doesn’t know about about a DogCollar class, it certainly can’t invoke the ReportSize method of the DogCollar class.

    // Can only use DogCollar within this assembly
    internal class DogCollar
    {
        // Marked as public, but effectively internal
        public double Size { get; set; }

        public DogCollar(double size)
        {
            Size = size;
        }

        // Also effectively internal
        public void ReportSize()
        {
            Console.WriteLine(string.Format("Collar is {0} in long", Size));
        }
    }

#713 – Declare Accessibility Explicitly

It’s always good practice to explicitly declare the accessibility of an item, for class members, struct members, and classes.  Declaring the accessibility makes it clear what the accessibility is for the item and avoids someone having to recall what the default accessibility is.

    public class Dog
    {
        // Stuff that's clearly public
        public string Name { get; set; }
        public int Age { get; set; }

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

        // Stuff that's clearly private
        private int numBarks;

        // Not obvious--private or public?
        //   (private, because class members are private by default)
        void DoBark()
        {
            Console.WriteLine("WOOF");
        }
    }

#712 – Accessibility Summary

Namespaces, types, class members, struct member, interface members and enumeration members all have an associated accessibility, dictated by the access modifer included in the member’s declaration.

The possible levels of accessibility are:

  • public – all code can access member
  • private – only code within the same type can access member
  • protected – code within type or subtype can access member
  • internal – code within the same assembly can access member
  • protected internal – code within the same assembly, within the same type, or within a subtype can access member

The type of member dictates which levels of accessibility are allowed:

  • class – can be public or internal  (default is internal)  [can only be public if parent class is public]
  • namespace – always public
  • class members – can be public, private, protected, internal or protected internal  (default is private)
  • struct members – can be public, private, or internal (default is private)
  • interface members – always public
  • enumeration members – always public

#699 – Types Are Implicitly Internal

When you define a type in C#, you can define its accessibility as either public or internal.  Public types are visible to all code.  Internal types are visible only to code within the same assembly.

By default, if you don’t include an access modifier when defining a type, the type’s accessibility will be internal.

In the example below, the Dog class will be visible only to code within the same assembly.

    // No access modifier => type is internal, visible
    //   only to code within the same assembly.
    class Dog
    {
        // Public properties
        public string Name { get; set; }
        public int Age { get; set; }

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

        public void Bark()
        {
            Console.WriteLine("Woof");
        }
    }