6

我有两个类,我想保存在单独的文件中。

namespace GridSystem
{
    public class Grid
    {
        public void AddItem(GridItem item)
        {
            item.InformAddedToGrid();
        }
    }
}

namespace GridSystem
{
    public class GridItem
    {
        public void InformAddedToGrid()
        {
            Debug.Log("I've been added to the grid");
        }
    }
}

如何确保不允许其他类调用 InformAddedToGrid?

我正在尝试模拟 Actionscript 命名空间,它可以在方法上使用,代替公共、私有、内部等。它并不能完全保护方法,而是强制在方法可以之前包含命名空间的额外步骤被访问。在 C# 中是否有替代方法?

4

5 回答 5

5

如果 GridItem 本身也可以对外界隐藏,我会考虑将 GridItem 作为嵌套类放在 Grid 中。这样它就不会在课堂外可见

http://www.codeproject.com/Articles/20628/A-Tutorial-on-Nested-Classes-in-C

于 2013-08-30T03:58:57.420 回答
1

一个非常丑陋的答案是将其设为私有并使用反射。

另一个丑陋的答案是,如果调用者错误,它会抛出异常。

这两者的执行速度也比正常调用慢得多。

我不认为有一个好的答案。C# 没有朋友。

于 2013-08-30T04:00:21.093 回答
1

不是你应该这样做,你应该按照 TGH 的建议做,为 GridItem 提供一个公共接口,并将 gridItem 嵌套在 Grid 中(然后在 Grid 上有一个工厂方法来创建项目并使用部分 Grid 类将它们放在单独的文件中) .

因为没有办法拥有朋友方法(你可以通过朋友类InternalsVisibleToAttribute

你可以这样做(但不要......)

public partial class Grid
{
   public void AddItem(GridItem item)
   {
      item.InformAddedToGrid();
   }
}        

public class GridItem
{
   public void InformAddedToGrid()
   {                
      if (new StackTrace().GetFrame(1).GetMethod().DeclaringType != 
                   typeof(Grid)) throw new Exception("Tantrum!");
      Console.WriteLine("Grid called in...");

   }
}

然后

 var g = new Grid();
 g.AddItem(new GridItem()); // works
 new GridItem().InformAddedToGrid(); // throws a tantrum...
于 2013-08-30T04:26:21.540 回答
0

恕我直言,答案很简单:访问修饰符只是为了提醒程序员一个类应该是公共/私有的意图。通过反思,你可以解除这些障碍。

你对一个类的使用完全掌握在你的手中:如果你的类在一个地方使用,那就去做吧。如果有的话,如果一个类有一种特殊的使用方式,请记录它——将它放在 XML 注释中。

也就是说,在这个特定的示例中,我相信由于GridItem不会将自身添加到网格中,因此通知它不是它的工作(如果“我还没有被添加到网格中”怎么办?)。我认为作为一种方法InformAddedToGrid属于您Grid班级的某个地方private,其中有一个添加项目的概念……假设那是AddItem(GridItem)真正的作用。

于 2013-08-30T04:31:59.227 回答
0

您可以按照 TGH 的建议使用嵌套类来执行此操作,但反之亦然。嵌套Grid在内部GridItem并设为InformAddedToGrid私有。在这里,我使用了一个嵌套的基类,因此公共 API 可以保持不变。请注意,程序集之外的任何人都不能继承,GridBase因为构造函数是内部的。

public class GridItem
{
    public class GridBase
    {
        internal GridBase() { }

        public void AddItem(GridItem item)
        {
            item.InformAddedToGrid();
        }
    }

    private void InformAddedToGrid()
    {
        Debug.Log("I've been added to the grid");
    }
}

public class Grid : GridItem.GridBase { }

另一种选择是GridItem显式实现内部接口。这样,程序集之外的任何人都不能按名称使用接口,因此不能调用InformAddedToGrid.

public class Grid
{
    public void AddItem(GridItem item)
    {
        ((IGridInformer)item).InformAddedToGrid();
    }
}

public class GridItem : IGridInformer
{
    void IGridInformer.InformAddedToGrid()
    {
        Debug.Log("I've been added to the grid");
    }
}

internal interface IGridInformer
{
    void InformAddedToGrid();
}
于 2013-08-30T04:47:04.200 回答