我知道问题inconsistent accessibility
经常被问到,但我的问题有所不同,因为我需要将其保密。
让我给出详细的解释:我有一个 static 类Line
和LingSegment
中的结构Line
,用户可以定义自己的{{ 1}},然后确保线段之间没有冲突。
架构如下:
LineSegment
并且当用户想要访问其线段时,他们只能按以下方式访问:
Line
我将public static class Line {
private struct LineSegment {
public LineSegment(int start, int end) {
Start = start;
End = end;
}
public readonly int Start;
public readonly int End;
}
// User created LineSegment
static public LineSegment Segment1() {
return new LineSegment(1, 2);
}
static public LineSegment Segment2() {
return new LineSegment(3, 6);
}
}
设为int start = Line.Segment1.Start;
int end = Line.Segment1.End;
的原因是:我只希望用户通过LineSegment
中的静态函数创建和访问private
,例如LineSegment
,Line
。这样我就可以使用反射添加一个单元测试,以获取Segment1
中的所有方法,并获取所有线段的开始和结束,然后可以判断线段之间是否存在冲突。
如果Segment2
是公开的,则用户可以仅使用Line
来入侵自己的代码,而我无法通过单元测试检测到它。我不希望他们在LineSegment
之外创建new Line.LineSegment(2, 5)
。
但是由于可访问性不一致,在C#中不允许制作LineSegment
。他们有什么解决方案可以满足我的要求吗?谢谢!
答案 0 :(得分:2)
关于什么:给他们访问权限,但警告他们...
public static class Line {
public struct LineSegment {
[Obsolete("DO NOT USE THIS DIRECTLY...")]
public LineSegment(int start, int end) {
Start = start;
End = end;
}
public readonly int Start;
public readonly int End;
}
// User created LineSegment
static public LineSegment Segment1() {
return _CreateSegment(1, 2);
}
static public LineSegment Segment2() {
return _CreateSegment(3, 6);
}
static private LineSegment _CreateSegment(int start,int end) {
//we don't want to trigger the warning ...
#pragma warning disable 618
return new LineSegment(3, 6);
#pragma warning restore 618
}
}
答案 1 :(得分:2)
在这些情况下,一种经过良好尝试的模式是定义一个公共接口,并使用一个公共(或内部)构造函数将内部类保持私有。这样,您可以防止在同一个项目上工作的其他开发人员(甚至将来您自己)也可以直接调用构造函数,同时仍然可以让他们访问类的相关属性。 因此,首先定义接口:
public interface ILineSegment
{
int Start { get; }
int End { get; }
}
然后是您的课程:
public static class Line
{
private struct LineSegment : ILineSegment
{
public int Start { get; }
public int End { get; }
public LineSegment(int start, int end)
{
Start = start;
End = end;
}
}
// User created LineSegment
static public ILineSegment Segment1()
{
return new LineSegment(1, 2);
}
static public ILineSegment Segment2()
{
return new LineSegment(3, 6);
}
请注意,LineSegment1和LineSegment2的返回值已从LineSegment(它是私有的,不能通过公共方法返回)更改为ILineSegment,后者是公共的并且可以返回。
答案 2 :(得分:0)
经过比较并征求意见,最后我选择使用Environment.StackTrace.Contains
来满足我的要求。
public static class Line {
public struct LineSegment {
public LineSegment(int start, int end) {
if (!Environment.StackTrace.Contains("MyNamespace.Line") || !Environment.StackTrace.Contains("UnitTest")) {
throw new InvalidOperationException("Outside code is not allowed to call its constructor. Please construct your property in this file refering to the example.");
}
Start = start;
End = end;
}
public readonly int Start;
public readonly int End;
}
// User created LineSegment
static public LineSegment Segment1() {
return new LineSegment(1, 2);
}
static public LineSegment Segment2() {
return new LineSegment(3, 6);
}
}