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

gex*_*ide 6 c# generics visibility covariance nested-class

我有一个通用类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
    }
}
Run Code Online (Sandbox Code Playgroud)

这可能吗?我之前从未听说过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)
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*ell 9

编辑:它看起来像是在Roslyn/C#6技术预览版上编译,但不能在MS C#5编译器或单声道编译器上编译.


是的,这样的-但请注意,其实内部T是在许多方面不必要的,如果你保留它-这将是它命名为有用TInner或东西,以避免混乱,因为TX<T>技术上比不同的事情X<>.IX<T>,即使他们会在实践中始终是相同的实际类型:

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
    }
}
Run Code Online (Sandbox Code Playgroud)


Laz*_*OfT -1

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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