【问题标题】:Generics using public interfaces and internal type parameters使用公共接口和内部类型参数的泛型
【发布时间】:2009-01-31 01:47:24
【问题描述】:

我有以下情况:

// 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 尽管是 internal,但仍然可以实现 public 接口。并且由于它实现了接口,那么它应该可用作 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,但我被解雇了,因为我不知道我在说什么。我的担心是否有效?

【问题讨论】:

    标签: c# .net generics interface


    【解决方案1】:

    根据C# generics上的这篇文章

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

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

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

    构造的类型 C 是 当它的所有组件都可以访问 C、T1、...、TN 可访问。更多的 准确地说,可访问域 对于构造类型是 可访问性的交叉点 未绑定泛型类型的域和 类型的可访问域 论据。

    【讨论】:

    • 那么,泛型实现的限制?值得报告连接吗?
    • 允许引用您的程序集不能强引用的类型似乎不合逻辑。
    • 太棒了。谢谢!关于类型交集的那句话让我找到了问题的根源!
    • @vanslly:为什么不呢?这似乎是限制派生类型比其父类型更易于访问的限制的特殊情况,但我不明白为什么能够定义此类类型没有用处。在许多情况下,从外部代码的角度来看,类型的父级应该是实现细节。在公共类型 W 和 X 都应该从公共类型 Z 派生的关系树中,有时有一个中间类型 Y 是有用的,外部代码应该对其有任何合法用途。在这种情况下,要求 Y 公开有什么好处?
    • @supercat 这不是实现细节,泛型定义是类型定义的一部分。当我听到“实现细节”时,我会想到组合和封装。我可以理解,可能存在通用参数类型未在类型(虚拟方法、属性等)的合同中公开的情况,但这对我来说似乎是特例。
    【解决方案2】:

    您面临的这个限制是有道理的,原因如下。

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

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

    因此,如果在单独的程序集中,以下内容将不起作用:

    MyClass<MyInternalConcrete> myInstance = new MySpecificClass();
    

    这里的单独程序集不知道 MyInternalConcrete,那么如何定义一个变量。

    【讨论】:

    • 这个说法是万无一失的。点完全明白。
    • 谢谢 - 我的思绪最近一直在这个空间里徘徊 - 很高兴我能增加我的两美分 :)
    • 我不记得您可以返回通用定义。它完美地解释了为什么它需要知道构成定义的所有类型。这不会发生在常规的类定义中,所以我假设同样适用于泛型。现在这很有意义。
    【解决方案3】:

    如果允许,您可以将 MyClass 从程序集中传递出去,突然之间,另一个程序集可以访问它不应该访问的东西 - MyInternalConcrete!

    【讨论】:

      猜你喜欢
      • 2018-09-15
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多