使用公共接口和内部类型参数的泛型

时间:2009-01-31 01:47:25

标签: c# .net generics interface

我有以下情况:

// A public interface of some kind   
public interface IMyInterface {   
    int Something { get; set; }   
}   

// An internal class that implements the public interface.   
// Despite the internal/public mismatch, this works.   
internal class MyInternalConcrete : IMyInterface {   
    public int Something { get; set; }   
}   

// A generic class with an interface-restricted type parameter.
// Note that the constraint on T uses the *public* interface.
// The instance is *never* exposed as a public, or even protected member.
public class MyClass<T> where T : IMyInterface, new() {   
    T myInterfaceInstance;   

    public MyClass() {   
        myInterfaceInstance = new T();   
    }   
}   

// Attempting to implement concrete class... Inconsistent Accessibility Error!   
public class MySpecificClass : MyClass<MyInternalConcrete>   
{   
}  

在尝试实现MySpecificClass时,我收到错误:

  

可访问性不一致:基类'App1.MyClass'不如类'App1.MySpecificT'

尽管内部,但MyInternalConcrete仍然可以实现公共接口,这一点很奇怪。并且由于它实现了接口,因此它可用作MyClass的类型参数 - 因为T受约束在公共接口而不是内部类。

如果MyClass暴露了T,我会理解它失败了,就像我们没有使用泛型一样会失败:

public class MyClass<T> where T : IMyInterface, new() {      
    T myInterfaceInstance;      

    public MyClass() {      
        myInterfaceInstance = new T();      
    }      

    // This will fail with an internal T - inconsistent accessibility!    
    public T Instance {      
        get { return myInterfaceInstance; }      
    }      
}

与上述相同,但没有泛型:

public class MyNonGenericClass {   
    MyInternalConcrete myInterfaceInstance;   

    public MyNonGenericClass() {   
        myInterfaceInstance = new MyInternalConcrete();   
    }   

    // This will fail - inconsistent accessibility! 
    // but removing it works, since the private instance is never exposed.   
    public MyInternalConcrete Instance {   
        get { return myInterfaceInstance; }   
    }   
}  

这是C#泛型的限制还是我只是误解了关于泛型如何工作的基本原理?

I also posted this thread on MSDN,但我被解雇,因为不知道我在说什么。我的担忧是否有效?

3 个答案:

答案 0 :(得分:7)

根据C# generics

上的这篇文章
  

“泛型类型的可见性是   泛型的交集   具有参数的可见性   类型即可。如果所有C的能见度,   T1,T2和T3类型设置为公开,   那么C的可见性就是   也是公众;但如果能见度   这些类型中只有一种是私有的,   那么C的可见性就是   私人“。

因此,虽然您的示例是可能的,但它不符合定义的规则。

有关更明确的来源,请参阅C# spec的第25.5.5节(第399页)。

  

构造的类型C是   可以访问所有组件   可以访问C,T1,...,TN。更多   确切地说,可访问性域   对于构造类型是   可访问性的交集   未绑定泛型类型的域和   该类型的可访问性域   参数。

答案 1 :(得分:5)

由于以下原因,您所面临的这种限制是有道理的。

C#强类型,所以......

为了能够引用它定义的程序集范围之外的MySpecificClass,必须知道它的参数类型,以便为其实例生成强类型引用;但是内部定义的单独组件不知道MyInternalConcrete。

因此,如果在单独的程序集中,以下内容将无效:

MyClass<MyInternalConcrete> myInstance = new MySpecificClass();

这里单独的程序集不知道MyInternalConcrete,所以如何定义变量。

答案 2 :(得分:1)

如果允许,你可以将MyClass传递出程序集,突然之间,另一个程序集可以访问它不应该访问的内容 - MyInternalConcrete!