为什么构造函数中不允许使用类型参数?

brg*_*ner 5 c#

方法有类型参数.为什么构造函数没有类型参数?

我认为有几个(不是很多)例子可供它们使用.我目前的问题如下:

internal class ClassA
{
   private readonly Delegate _delegate;

   public ClassA<T>(Func<T> func)
   {
     _delegate = func;
   }
}
Run Code Online (Sandbox Code Playgroud)

A Delegate对我的班级来说已经足够了.但要将其作为方法组传递,我需要将参数定义为a Func<T>.

Dav*_*son 2

阅读 C# 规范后,它实际上确实有意义,但可能会令人困惑。

每个类都有一个关联的实例类型,对于泛型类声明,实例类型是通过从类型声明创建构造类型来形成的,每个提供的类型参数都是相应的类型参数。

class C<T>
{ 
}
Run Code Online (Sandbox Code Playgroud)

C<T>是构造类型,并且在使用类型参数构造类型的过程中将创建实例类型。

C<String> c = new C<String>();
Run Code Online (Sandbox Code Playgroud)

编译器采用构造类型,并使用提供的类型参数创建C<T>实例类型。C<String>泛型只是一个编译时构造,一切都在运行时以封闭构造类型的形式执行。

现在让我们来回答你的问题并在这里进行测试。

class C
{
    public C<T>() 
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

这是不可能的,因为您正在尝试构造一个不存在的类型。

C c = new C<String>();
Run Code Online (Sandbox Code Playgroud)

和之间的implicitorexplicit换算是什么?空无一人。这甚至没有意义。CC<String>

因为C本例中是非泛型类型,所以实例类型就是类声明本身。那么您希望如何C<String>构建C

您想要做的事情的正确声明是这样的。

internal class Class<T> 
{
    private readonly Delegate _delegate;

    public Class(Func<T> function) 
    {
        _delegate = function;
    }
}
Run Code Online (Sandbox Code Playgroud)

这里因为我们有一个构造类型Class<T>,所以编译器可以创建正确的实例类型。

Func<String> function = new Func<String>(() => { return String.Empty; });
Class<String> c = new Class<String>(function);
Run Code Online (Sandbox Code Playgroud)

如果您尝试按照您在问题中想要的方式进行操作。

Func<String> function = new Func<String>(() => { return String.Empty; });
Class c = new Class<String>(function);
Run Code Online (Sandbox Code Playgroud)

构造类型将为Class<String>,它与 type 不同,并且两者之间都C没有implicit或转换。explicit如果编译器允许这样做,C则会处于某种未知且无法使用的状态。

关于构造类型,您需要了解的是这一点。

class C<T>
{
    public C<T>() 
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然您无法显式声明泛型构造函数,但它是有效的,但只能在运行时作为封闭类型构造函数。

C<String> c = new C<String>();
Run Code Online (Sandbox Code Playgroud)

在编译时,创建以下构造函数。

public C<String>() 
{
}
Run Code Online (Sandbox Code Playgroud)

这就是为什么这是有效的:

C<String> c = new C<String>(); // We just used the closed type constructor
Run Code Online (Sandbox Code Playgroud)

如果你想要的被允许,这样的事情就可能发生。

class C<T>
{
    public C<U>() 
    {
    }
}

// ???
C<String> c = new C<Int32>();
Run Code Online (Sandbox Code Playgroud)

您现在可以看到如果允许构造的话将会出现的问题。希望这能提供一些见解,该规范相当长,并且有很多很多部分涵盖泛型、类型参数、构造类型、封闭和开放类型、绑定和非绑定。

它可能会变得非常混乱,但编译器规则不允许这样做是一件好事。