Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An internal property in C# is a class, struct, or interface member that provides a flexible mechanism to read, write, or compute a value, with its accessibility restricted strictly to the assembly in which it is declared. Any code within the same compiled assembly (typically a .dll or .exe) can access the property, while code residing in external assemblies cannot.
public class Employee
{
    // Auto-implemented internal property (generates a hidden backing field)
    internal string DepartmentCode { get; set; }

    // Computed internal property (no backing field)
    internal bool HasDepartment => !string.IsNullOrEmpty(DepartmentCode);
}

Accessor Mechanics and Asymmetric Accessibility

The internal modifier can be applied to the property as a whole, or it can be applied asymmetrically to individual get or set accessors to create granular access control. When applying an access modifier to a specific accessor, the modifier must be more restrictive than the modifier applied to the property itself. Because internal is more restrictive than public, it is frequently applied to the set accessor of a public property.
public class SystemConfiguration
{
    // The property is public, but the setter is restricted to the current assembly
    public int MaxWorkerThreads { get; internal set; }
    
    // The property is internal, but the setter is further restricted to the declaring class
    internal string DiagnosticLogPath { get; private set; }
}

Compilation and Scoping Rules

  • Assembly Boundary: The Common Language Runtime (CLR) enforces the internal boundary at the assembly level, not the namespace level. Two classes in the exact same namespace but compiled into different assemblies cannot access each other’s internal properties.
  • Type Accessibility: An internal property can be declared inside a public, internal, or private type. However, if the containing type is internal, a public property inside it effectively behaves as internal, as the type itself cannot be accessed outside the assembly.
  • Interface Implementation: An internal property cannot implicitly implement a public property defined in an interface. Starting with C# 8.0, interfaces can explicitly declare members with restricted access modifiers, including internal. Because implicit interface implementations in C# must always be public regardless of the interface member’s modifier, an internal interface property must be implemented using explicit interface implementation. Explicit implementations prohibit the use of any access modifiers and require a defined body for the accessors.
public interface ISystemState
{
    // Internal interface property (C# 8.0+)
    internal string StateCode { get; set; }
}

public class SystemState : ISystemState
{
    private string _stateCode;

    // Explicit interface implementation; access modifiers are prohibited, and a body is required
    string ISystemState.StateCode 
    { 
        get => _stateCode; 
        set => _stateCode = value; 
    }
}

The InternalsVisibleTo Attribute

The strict assembly boundary of an internal property can be explicitly bypassed at compile-time using the [InternalsVisibleTo] assembly-level attribute. This attribute instructs the compiler to treat a specified external assembly as a “friend” assembly, granting it the same access rights to internal properties as the declaring assembly.
// Placed in the AssemblyInfo.cs or project file of the declaring assembly
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("ExternalAssembly.Name")]
Master C# with Deep Grasping Methodology!Learn More