#698 – Type Members Are Implicitly Private

You use access modifiers to define the accessibility of members within a class (publicprivate, protected, internal or protected internal).

If you omit the access modifier entirely, the class member defaults to being private.  This is true for all class members, including constants, fields, properties, methods, indexers, events, constructors and nested types.

In the example below, the Description property, NumDogs static property and the ChaseTail method are all effectively private members, because their declaration does not include an access modifier.

    public class Dog
    {
        // Public properties
        public string Name { get; set; }
        public int Age { get; set; }

        // Implicitly private
        string Description { get; set; }

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

        // Implicitly private
        static int NumDogs { get; set; }

        // Implicitly private
        void ChaseTail()
        {
            Console.WriteLine("I'm chasing my tail");
        }
    }

#627 – Accessibility of Nested Types in a struct or a class

When you define a type within the scope of a class (a nested type), the accessibility of the nested type can be one of the following

  • public
  • protected internal
  • protected
  • internal
  • private  (default)

When you define a type within a struct, the choices for accessibility of the nested type are more limited and include:

  • public
  • internal
  • private  (default)

Remember that the outer type (the class or struct) has more limited accessibility choices:

  • public
  • internal  (default)

#624 – Accessibility of a Nested Class

When you define one class within the scope of another (a nested class), you have several choices for the accessibility of the inner class.  The inner class can be defined with any of the following access modifiers:

  • public – the class is accessible from any code, within the assembly where it’s defined or from a different assembly
  • protected internal – class accessible from any subclass of the outer class or from any code within the same assembly
  • protected – class accessible from any subclass of the outer class
  • internal – class accessible from any code within the same assembly
  • private – class accessible only from within the outer class

Notice that the choices for accessibility of a nested class are much broader than for a class defined in a standard namespace scope (public, internal).

#614 – Subclass Accessibility

A class can be defined with one of two different levels of accessibility:

  • public – all code can use the class
  • internal – only code in the same .exe or .dll can use the class

When you define a subclass, the accessibility of the subclass must be the same as, or less accessible than, the parent class.

This means:

  • If the parent class is public
    • Subclass can be public or internal
  • If the parent class is internal
    • Subclass must be internal

#612 – Members of an Interface Are Implicitly Public

The idea of an interface is to define a contract that a class can choose to implement.  Since an interface is a public definition of a contract, it doesn’t make sense for members of an interface to be private.  This means that all members in an interface are implicitly public.

    public interface IDogStuff
    {
        // Implicitly public
        bool CanBark { get; set; }
        void Bark();

        // Compile-time Error: The modifier 'public' is not valid for this item
        public void Fetch();

        // Compile-time Error: The modifier 'private' is not valid for this item
        private void PeeOnTree();
    }

#611 – Accessibility of Members in a struct

Methods, field and properties within a struct can have one of three access modifiers, dictating the visibility of these members.

  • public – all code has access
  • private – only code within the struct has access
  • internal – code within the defining assembly has access
    public struct DogBark
    {
        public string BarkSound;
        public int BarkLength;

        // Constructor is public
        public DogBark(string barkSound, int barkLength)
        {
            BarkSound = barkSound;
            BarkLength = barkLength;
            hash = barkSound.GetHashCode();
        }

        // internal - accessible from code in the same assembly
        internal int GetHash()
        {
            return hash;
        }

        // private - accessible from code in this struct
        private int hash;
    }

#322 – Class Accessibility

The members of a class all have an associated access modifier, which defines their accessibility.  A class itself also has an accessibility level, which dictates which code can make use of the class.

The two types of accessibility for a class are:

  • public – all code can use the class
  • internal – only code in the same .exe or .dll can use the class

In the code below, the Dog class, defined in DogLibrary.dll, is marked as internal.  This means that only code within the same DLL (highlighted blue) can create and use instances of the Dog class.

The Program class in Program.exe has access to the DogKennel class, but not the Dog class.  It can create an instance of a DogKennel, but not an instance of a Dog.

    class Program
    {
        static void Main()
        {
            // Ok
            DogKennel k = new DogKennel();
            k.EverybodyBark();

            // ERROR
            Dog d = new Dog("Kirby");

#321 – Accessibility of Constants

As with other class members, you can apply access modifiers to constants defined in a class to define their accessibility.  Accessibility dictates what other code has access to the constant’s value.

  • public – All code has access
  • private – Only code in the defining class has access
  • protected – Code in the defining class or derived classes has access
  • internal – All code in the defining assembly has access
  • protected internal – Code in the defining assembly or in derived classes has access
        // All code has access
        public const string PluralOfDog = "Dogs";

        // Only this class has access
        private const Breeds DefaultBreed = Breeds.Retriever;

        // Subclass has access
        protected const string DefaultDogName = "Bowser";

        // Code in same assembly has access
        internal const string TargetArchitecture = "x86";

        // Code in same assembly or subclass has access
        protected internal const int DeckSize = 52;

#315 – Accessibility of Static Methods and Properties

Like instance methods and properties, you can define the accessibility of static methods and properties using access modifiers.  As with instance members, access modifiers on static members indicates what code has access to the member.

  • public – All code has access
  • private – Only code in the defining class has access
  • protected – Code in the defining class or derived classes has access
  • internal – All code in the defining assembly has access
  • protected internal – Code in the defining assembly or in derived classes has access
        // All code has access
        public static Dog MakeNewDog()
        {
        }

        // Only this class has access
        private static void InitSomeStaticData()
        {
        }

        // Subclass has access
        protected static void InitOtherStuff()
        {
        }

        // Code in same assembly has access
        internal static void RunSomeCalcs()
        {
        }

        // Code in same assembly or subclass has access
        protected internal static void DoOtherStuff()
        {
        }

#314 – Access Modifiers Are Not Allowed on Static Constructors

Because you can’t call a static constructor directly, you can’t include an access modifier (e.g. public, private) when defining a static constructor.  Static constructors are defined without access modifiers.

        static Dog()
        {
            Motto = "We serve humans.  And lick ourselves.";
        }

The compiler will generate an error if you try to include an access modifier.