为什么我可以访问名称空间之外的内部方法?

问题描述

我试图理解访问修饰符,但是我对如何使用internal感到困惑。

我在一个类似以下名称间的类中拥有一个类:

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

然后在像这样的继承类中实现:

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

所以我现在创建一个类来使用不属于名称间的Grid:

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         
    }
}

但是由于某些原因,我可以访问应该是内部的功能

这是为什么?我不想公开此函数,我只希望我的Map类可以访问它,该类共享相同的Grids名称空间,并将控制我要公开的内容。我的MapGenerator类是否可以访问而甚至不属于名称空间?

我是否误解了内部的工作原理?

解决方法

根据文档internal (C# Reference)

内部类型或成员只能在 文件中访问 相同的 程序集

根据您的评论

[很难]设计一种隐藏这些功能的方法,但仍然会给 访问特定班级。

标准的访问修饰符相当有限,您需要将调用代码放在同一 assembly 中才能使用internal。此外,除非在运行时执行此操作,否则无法授予调用类的访问列表。

但是,您可以使用Explicit Interface Implementation。这不会完全限制访问,但是会这样做,因此您需要明确要求它,并在其他时间隐藏它。

public interface IGrid
{
    Vector2Int ToGrid(...);
}

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

用法

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