簡體   English   中英

可訪問性不一致:返回類型小於方法

[英]Inconsistent accessibility: return type is less than method

我知道經常會問到inconsistent accessibility的問題,而我的問題也有所不同,因為我需要將其保密。

讓我給詳細的解釋:我有一個靜態Line ,以及一個struct LingSegmentLine ,用戶可以自己定義LineSegmentLine ,我需要確保有線段之間沒有沖突。

架構如下:

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的原因是:我只希望用戶通過Line靜態函數(例如Segment1Segment2創建和訪問LineSegment 這樣我就可以使用反射添加一個單元測試,以獲取Line所有方法,並獲取所有線段的起點和終點,然后判斷線段之間是否存在沖突。

如果LineSegment是公開的,則用戶僅可以使用new Line.LineSegment(2, 5)來入侵自己的代碼,而我無法通過單元測試檢測到它。 我不希望他們在Line之外創建LineSegment

但是由於可訪問性不一致,因此在C#中不允許制作LineSegment 他們有什么解決方案可以滿足我的要求嗎? 謝謝!

那怎么辦:給他們訪問權限但警告他們...

    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
       }
    }

在這些情況下,一種經過良好嘗試的模式是定義一個公共接口,並使用一個公共(或內部)構造函數將內部類保持私有。 這樣,您可以防止在同一個項目上工作的其他開發人員(甚至將來您自己)也可以直接調用構造函數,同時仍然可以讓他們訪問類的相關屬性。 因此,首先定義接口:

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,后者是公共的並且可以返回。

經過比較並征求意見,最后我選擇使用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);
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM