0

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?

WDUK
  • 1,412
  • 1
  • 12
  • 29
  • Internal types or members are accessible ***only*** within files in the same ***assembly*** – TheGeneral Aug 24 '20 at 03:20
  • Did you read [the docs](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/internal)? Notice the word "assembly", not "namespace". – Sweeper Aug 24 '20 at 03:20
  • Ah wasn't sure what that meant. Damn thats annoying then - difficult to design a way to hide these functions but still give access to a specific class. – WDUK Aug 24 '20 at 03:22
  • `difficult to design a way to hide these functions but still give access to a specific class.` protected perhaps? – mjwills Aug 24 '20 at 03:31
  • How do i expose protected to the `Map` class which does not inherit it but has a reference of `Grid` ? Basically i want `Map` to control what methods are exposed from the `Grid` class which the `MapGenerator` will call upon to generate the map. – WDUK Aug 24 '20 at 03:32
  • Are inner classes an option? – mjwills Aug 24 '20 at 03:38

1 Answers1

1

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
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • Ah i see, surprised C# has never implemented more ways to control the access of functions such as having a controller to define what should be public or protected of another class. Would be quite useful to make usage of libraries a bit less cluttered. – WDUK Aug 24 '20 at 03:39