Search code examples
c#abstractionaccess-modifiers

Why do i have access to internal methods outside of the namespace?


I am trying to understand access modifiers but i am a bit confused with how to use internal.

I have class in a namespace that looks like this:

namespace Grids
{
    public abstract class Grid
    {
        internal abstract Vector2Int ToGrid(float worldX, float worldY);
        internal Vector2Int ToGrid(Vector3 worldPoint) => ToGrid(worldPoint.x, worldPoint.z);
        internal Vector2Int ToGrid(Vector2 worldPoint) => ToGrid(worldPoint.x, worldPoint.y);
    }
}

This is then implemented in an inherited class like so:

namespace Grids
{
    public class RectGrid : Grid
    {
        public int Width;
        public int Height;
        public Grid(int w, int h)
        {
             Width = w;
             Height = h;
        }
        internal override Vector2Int ToGrid(float worldX, float worldY)
        {
            int col = Mathf.FloorToInt(worldX / Width);
            int row = Mathf.FloorToInt(worldY / Height);
            return new Vector2Int(col, row);
        }
    }
}

So i now make a class to use this Grid thats not part of the namespace:

using Grids;
using UnityEngine;

public class MapGenerator : MonoBehaviour
{
    private RectGrid _rectGrid;
    
    void Awake() {
        _rectGrid = new RectGrid(1,1);   
        _rectGrid.ToGrid(Vector3.zero); // why do i have access to this function         
    }
}

Yet for some reason i have access to the functions which are suppose to be internal:

Why is this ? I don't want to expose this function i want it only accessible to my Map class which shares the same Grids namespace and will control what i do expose. Yet my MapGenerator class has access without even being part of the namespace?

Have i misunderstood how internal works here?


Solution

  • As per the documentation internal (C# Reference)

    Internal types or members are accessible only within files in the same assembly

    As per your comment

    [It's] difficult to design a way to hide these functions but still give access to a specific class.

    The standard access modifiers are fairly limited, you would need put the calling code in the same assembly to use internal. Additionally there is no way to grant an access list for calling classes unless you do this at runtime.

    However, you could use an Explicit Interface Implementation. This will not completely limit access, but it will make it so you need to explicitly ask for it, and hides it any other time.

    public interface IGrid
    {
        Vector2Int ToGrid(...);
    }
    
    public abstract class Grid : IGrid
    {
       Vector2Int IGrid.ToGrid(...) {}
    }
    

    Usage

    var rectGrid = new RectGrid();
    ((IGrid)rectGrid).ToGrid(); // you need to explicitly cast to the interface