可访问性不一致:返回类型小于方法

时间:2018-10-25 08:00:11

标签: c# visibility

我知道问题inconsistent accessibility经常被问到,但我的问题有所不同,因为我需要将其保密。

让我给出详细的解释:我有一个 static LineLingSegment中的结构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,例如LineSegmentLine。这样我就可以使用反射添加一个单元测试,以获取Segment1中的所有方法,并获取所有线段的开始和结束,然后可以判断线段之间是否存在冲突。

如果Segment2是公开的,则用户可以仅使用Line来入侵自己的代码,而我无法通过单元测试检测到它。我不希望他们在LineSegment之外创建new Line.LineSegment(2, 5)

但是由于可访问性不一致,在C#中不允许制作LineSegment。他们有什么解决方案可以满足我的要求吗?谢谢!

3 个答案:

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