C#:私有内部接口是不是可能?

Posted

技术标签:

【中文标题】C#:私有内部接口是不是可能?【英文标题】:C#: Is a private inner interface possible?C#:私有内部接口是否可能? 【发布时间】:2014-09-09 08:22:01 【问题描述】:

我有一个通用类X<T>;这个类有一个协变部分,我希望能够协变地访问它。所以我把它分解成一个接口IX<out T>。但是,我希望这个接口只对类本身可见,因为它还包含被称为private 的方法。

即,在类本身内部,我可以向上转换为 IX<T> 并协变地使用它。例如:

class X<T> : IX<T> 

    private interface IX<out T> // the private covariant interface
         void foo();
    

    // It grants access to the private method `foo`
    private T foo()...
    public T IX.foo() return foo(); 

    private static void someMethod(IX<T> x) 
        // Here I can use `x` covariantly
    

这可能吗?我以前从未听说过private 嵌套接口,因为私有接口通常毫无意义。但是,对于泛型,这样的接口对于实现“仅私有的协变”是必要的。

当我尝试编译它时,我收到以下错误:

foo.cs(1,14): error CS0246: The type or namespace name `IX' could not be found. Are you missing an assembly reference?
foo.cs(9,14): error CS0305: Using the generic type `X<T>.IX<S>' requires `1' type argument(s)

这基本上很清楚,泛型类型的内部类型需要外部类型的类型参数。有没有办法让这段代码正确编译?

【问题讨论】:

为什么不是私有类,而是接口? @Tigran:因为一个类不能被声明为协变的,我可能想从另一个类继承。 你不能只声明你的内部接口,让它只在你的程序集中可见吗? @Sahuagin:抱歉,忘记添加我的编译器的输出了 :) @Brizio:这也可以,但不会授予我所针对的非常严格的访问限制。 【参考方案1】:

编辑:看起来这可以在 Roslyn / C# 6 tech preview 上编译,但不能在 MS C# 5 编译器或单声道编译器上编译。


是的,就像这样 - 但请注意,实际上内部的 T 在很多方面都是不必要的,如果你保留它 - 将其命名为 TInner 或避免混淆的名称会很有用,因为 TX&lt;T&gt;在技术上X&lt;&gt;.IX&lt;T&gt; 不同,尽管它们在实践中总是相同的实际类型:

class X<T> : X<T>.IX<T>


    private interface IX<out TInner>
     // the private covariant interface
        void foo();
    

    // It grants access to the private method `foo`
    private T foo()  throw new NotImplementedException(); 
    void X<T>.IX<T>.foo()  throw new NotImplementedException(); 

    private static void someMethod(IX<T> x)
    
        // Here I can use `x` covariantly
    

【讨论】:

对于一个类的private 的东西可以在外部(即类外)访问,这似乎很奇怪。 @James 它没有被外部访问。 所以不能通过X&lt;T&gt;.IX&lt;T&gt;从同一个程序集中的另一个类访问它? @James 不;它只能被X&lt;T&gt; 和声明为inside X&lt;T&gt; 的其他类型使用。 这会导致编译器错误:循环基类依赖涉及 'X' 和 'X.IX'【参考方案2】:

为了让它编译并将你的界面的可见性限制在你的程序集中,你可以将它标记为内部。问题是,如果它被声明为内部类型,您的班级将看不到它。这段代码应该可以工作:

internal interface IX<out T> // the private covariant interface
 
    T foo();


class X<T> : IX<T> 

    // It grants access to the private method `foo`
    private T foo() return default(T); 
    T IX<T>.foo() return foo(); 

    private static void someMethod(IX<T> x)
    
        // Here I can use `x` covariantly
    

这样接口仍然是私有的,但由于它不再是内部类型,它可以在你的类上使用。

【讨论】:

是否允许命名空间级别的private 接口?我以为只有internalpublic 被允许在那里......是的,试过了。有一个编译器错误说明了这一点。 你说得对,我使用 Linqpad 进行了测试,它显然将所有内容都放在了一个内部类中。

以上是关于C#:私有内部接口是不是可能?的主要内容,如果未能解决你的问题,请参考以下文章

私有的嵌套类(内部或静态)是不是可能具有具有公共访问权限的方法?

c#接口公共私有[重复]

抽象类中的私有非抽象成员和继承 C#

C#:使用实现私有接口的对象参数测试方法

在c#私有方法中正确测试接口[重复]

私有成员是不是应该在惯用的 C# 中显式声明为私有? [关闭]