#1,024 – Exposing internal Members to Another Assembly

Internal class members are accessible within the class in which they are defined, as well as from other code within the same assembly.

Suppose that we define an internal field as follows:

    public class Dog
    {
        internal static int DogCount = 0;

        public string Name;

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

Code within another assembly that is using the Dog class will not be able to access the DogCount property.

It’s sometimes useful, however, to make internal members accessible to testing code that exists in another assembly.  We can do this with the InternalsVisibleTo attribute.  In the example above, we can define the following within AssemblyInfo.cs in the library containing the Dog class.

[assembly: InternalsVisibleTo("DogTester")]

Code within the DogTester assembly can now access internal members in Dog.

            Dog d = new Dog("Kirby");
            Dog d2 = new Dog("Jack");

            Console.WriteLine("We've created {0} dogs", Dog.DogCount);
Advertisement

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

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

#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");

#308 – Protected Internal Class Members

Class members marked with the accessibility keyword protected internal are accessible from within the same class, from within code in classes that derive from the class, or from within code in classes within the same assembly.

In the picture below, the Dog.DoBark method is marked as protected internal.  The code in any of the blue blocks can call this method.

#307 – Internal Class Members

Class members marked with the accessibility keyword internal are accessible from within the same class, or from within the code of any classes that exist in the same assembly.

In the picture below, the Dog.DoBark method is marked as internal.  The code in any of the blue blocks can call this method.

Notice that code in the Shepherd class cannot call DoBark, even though it’s in a subclass of Dog.  Also notice that code in OtherClass can call DoBark, even though it’s not a subclass of Dog.  Only code in the same assembly as the Dog class has access to the DoBark method.

#303 – Accessibility of Class Members

Members of a class can have different kinds of accessibility.  An accessibility keyword indicates what source code can access the member.  The different types of accessibility are:

Accessibility Keyword Description
public All code can access the member
private Only other code in the class can access the member
protected Code in this class or any class that inherits from this class can access
internal Code in files in the same assembly (.dll or .exe) can access
protected internal Code in the same assembly or in classes that inherit from this class can access

Accessibility keywords can apply to the following kinds of members of a class: fields, properties, methods, constants, indexers, events, constructors and nested types.  They can apply to both instance and static members.