我有两个课程,我想保留在不同的文件中。
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#中有替代方法吗?
答案 0 :(得分:5)
如果GridItem本身也可以从外部世界隐藏,我会考虑将GridItem作为嵌套类放在Grid中。这样,它就不会在课堂外看到
http://www.codeproject.com/Articles/20628/A-Tutorial-on-Nested-Classes-in-C
答案 1 :(得分:1)
一个非常难看的答案是将其设为私有并使用反射。
另一个丑陋的答案是,如果调用者错误,它会抛出异常。
这两个都比正常通话慢得多。
我认为没有一个好的答案。 C#没有朋友。
答案 2 :(得分:1)
不是你应该这样做,你应该做TGH建议的事情,有一个GridItem的公共接口,并且gridItem嵌套在Grid中(然后在Grid上有一个工厂方法来创建Items并使用部分Grid类让它们进入单独的文件)。
因为没有办法使用朋友方法(你可以通过InternalsVisibleToAttribute
做朋友课程)
你 COULD 这样做(但不要......)
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...
答案 3 :(得分:0)
恕我直言答案很简单:访问修饰符只是为了提醒程序员 intent 一个类应该是公共/私有的。通过反思你可以解除这些障碍。
您对课程的使用掌握在您手中:如果您的课程意味着仅在一个地方使用,那么就这样做。如果有的话,如果一个类有一种特殊的使用方式,请记录它 - 把它放在XML注释中。
那就是说,在这个具体的例子中我会相信,因为GridItem
没有将自己添加到网格中,所以通知它不是它的工作(如果“我还没有添加到网格“?)。我认为InformAddedToGrid
属于Grid
类作为private
方法的某个地方,其中有添加项的概念...假设是{{1}确实如此。
答案 4 :(得分: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();
}