【问题标题】:Why do i have access to internal methods outside of the namespace? [duplicate]为什么我可以访问命名空间之外的内部方法? [复制]
【发布时间】:2020-12-12 16:38:54
【问题描述】:

我正在尝试理解访问修饰符,但我对如何使用 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);
        }
    }
}

所以我现在创建一个类来使用这个不属于命名空间的网格:

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 类甚至可以访问而不是命名空间的一部分?

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

【问题讨论】:

  • 内部类型或成员可在同一程序集的文件中访问/跨度>
  • 你读过the docs吗?注意“程序集”这个词,而不是“命名空间”。
  • 啊不知道那是什么意思。太烦人了——很难设计一种方法来隐藏这些功能,但仍然可以访问特定的类。
  • difficult to design a way to hide these functions but still give access to a specific class. 可能受保护?
  • 我如何将 protected 暴露给 Map 类,该类不继承它但具有 Grid 的引用?基本上我希望Map 控制从Grid 类公开的方法,MapGenerator 将调用这些方法来生成地图。

标签: c# abstraction access-modifiers


【解决方案1】:

根据文档internal (C# Reference)

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

根据您的评论

[It's] 很难设计一种方法来隐藏这些功能,但仍然提供 访问特定类。

标准的访问修饰符相当有限,您需要将调用代码放在同一个程序集中才能使用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

【讨论】:

  • 啊,我明白了,令我惊讶的是,C# 从来没有实现过更多的方法来控制函数的访问,例如让控制器定义什么应该是公共的或另一个类的保护。使库的使用不那么混乱会非常有用。
猜你喜欢
  • 2017-12-27
  • 2011-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
相关资源
最近更新 更多