具有泛型和“InternalsVisibleTo”的内部构造函数

Internal constructor with generics and `InternalsVisibleTo`

在使用 InternalsVisibleTo 属性时,是否可以使用带有内部无参数构造函数的 class 来与泛型一起使用?我知道您可以使用工厂方法或反射等...来执行此操作,但最好不要使用这些方法。

如果这不可能,这是设计使然吗?如果是,为什么?

取下面的代码:

Class图书馆

[assembly: InternalsVisibleTo("testapp")]

namespace Test
{
    public class MyClass
    {
        internal MyClass()
        {
        }
    }
}

申请

namespace Test
{
    public class GenericClass<T> where T: new()
    {
        // Compiles fine due to the `InternalsVisibleTo` attribute
        MyClass c = new MyClass();

        T t = new T();
    }

    public class ConsumerClass
    {
        // gives the error: 'MyClass' must be a non-abstract type with a public
        // parameterless constructor in order to use it as parameter 'T' in the
        // generic type or method 'GenericClass<T>'
        GenericClass<MyClass> g;
    }
}

这是设计使然。来自 the spec,第 4.4.4 节:

If the constraint is the constructor constraint new(), the type A must not be abstract and must have a public parameterless constructor. This is satisfied if one of the following is true:

  • A is a value type, since all value types have a public default constructor (§4.1.2).
  • A is a type parameter having the constructor constraint (§10.1.5).
  • A is a type parameter having the value type constraint (§10.1.5).
  • A is a class that is not abstract and contains an explicitly declared public constructor with no parameters.
  • A is not abstract and has a default constructor (§10.11.4).

至于为什么这样设计,可能只是因为没有人将其设计为与 InternalsVisibleToAttribute 一起使用。这将需要额外的工作来指定、实施和测试该功能,我怀疑要么没有人想到它,要么被认为不值得付出努力。

这当然没有违反 CLR 中的任何内容。 所以我拿了一个 dive into Roslyn 将约束显示为:

        if (typeParameter.HasConstructorConstraint && !SatisfiesConstructorConstraint(typeArgument.Type))
        {
            // this must be a non-abstract type with a public parameterless constructor                 
            return false;
        }

其中 SatisfiesConstructorConstraint 只是检查

HasPublicParameterlessConstructor((NamedTypeSymbol)typeArgument) && !typeArgument.IsAbstract;

如您所料,HasPublicParameterlessConstructor 只检查是否有任何构造函数是:

constructor.DeclaredAccessibility == Accessibility.Public;

他们没有为 InternalsVisibleTo 属性实现任何回旋余地。类型信息是可用的。也许打开一个问题?