C# 在引入其他泛型类型的泛型类上是否可能有一个构造函数?

C# 在引入其他泛型类型的泛型类上是否可能有一个构造函数?,c#,generics,C#,Generics,我试图构建一个泛型类,它的构造函数引入了一个额外的类型,但是编译器说不 我不太明白为什么以下方法不起作用: public class Foo<T> { public Foo<T,TBar>(TBar tBar) { ... } } 公共类Foo { 公共食品(待定) { ... } } 这并不重要,因为我可以使用fluent api编写类(这可能是首选),但我仍然想理解为什么我不能。我能想到的唯一解释是编译器不喜欢方法级泛型类型声明与类

我试图构建一个泛型类,它的构造函数引入了一个额外的类型,但是编译器说不

我不太明白为什么以下方法不起作用:

public class Foo<T>
{
    public Foo<T,TBar>(TBar tBar)
    {
    ...
    }
}
公共类Foo
{
公共食品(待定)
{
...
}
}

这并不重要,因为我可以使用fluent api编写类(这可能是首选),但我仍然想理解为什么我不能。我能想到的唯一解释是编译器不喜欢方法级泛型类型声明与类级泛型类型声明混合使用。

这是不可能的。构造函数不像方法那样被调用,它只通过指定类名(在
new
关键字之后)来调用。另一方面,普通方法可以有其他泛型类型参数。

否。只有类型和方法可以是泛型的。不能有泛型属性、事件、字段、构造函数或终结器


请注意,这与包含类型是否为泛型无关——基本上,这只是语言(我怀疑是CLR)的一个限制。(有趣的是,Java确实允许泛型构造函数,但Java中的泛型与C中的泛型截然不同。)

正如Jon自己指出的那样,这是不可能直接实现的,但有一个通用的解决方法,可以解决这个问题:

public class Foo<T,TBar>
{
    public Foo(TBar tBar)
    {
        //do something
    }
}
公共类Foo
{
公共食品(待定)
{
//做点什么
}
}

IIUC,为此调用
new
,这正是您想要的

构造函数是一种特殊的方法。你有没有注意到类名称和
new
关键字后面出现的偏执

Person jack = new Person();
Person()具有方法调用语法。这是因为它不是类型
Person
,而是一个与类型本身完全相同的方法,这是由于要调用以初始化类型的语言的设计

引用C规范:

构造函数声明器的标识符应命名在其中声明实例构造函数的类。如果指定了任何其他名称,则会发生编译时错误

17.10实例构造函数
实例构造函数是实现初始化类实例所需操作的成员。实例构造函数是使用构造函数声明声明的:

如果查看构造函数公式,则根本看不到任何通用声明标记:

构造函数声明器:
标识符(形式参数listopt)构造函数初始值设定项Opt


你不能,你需要使用工厂方法。这并不是一个重复的问题,但是一个相关的问题说明了语言设计者需要解决什么样的问题才能做到这一点。(事实上,这可能是一个重复的问题。我不确定你的问题是否更多地集中在“是否可能”或“为什么不可能”。)这实际上可能是处理你提到的问题的另一种方式。肯定有一个实际的问题(“有可能”)在探索学术上的回应(“为什么没有?”)。我喜欢这里的工厂方法。创建对象现在需要
new Foo(tBar)
而不是
new Foo(tBar)
,它不允许从参数的类型推断
tBar
。这意味着我的“IIUC”是伪造的。我被纠正了。仍然没有删除这个答案,因为其他人可能会犯同样的错误。不过感谢你的想法…我认为Pragmateek的工厂方法的想法会是一个更干净的方法,尽管不会改变整体类型。但是,所有这些都不会禁止有泛型构造函数这样的东西。碰巧它不被支持,但它可以被支持,你的答案中的所有内容都是这样的……是的@JonSkeet,你是对的。我刚刚更新了答案。谢谢你的注意。“这只是语言的一个限制”当然足够了。我觉得如果对这个特性有巨大的需求,他们就可以把它写进编译器中。但它并不是一个优雅的或非常有用的特性,因此限制是强加的,而不是不可行的。@BlackjacketMack:我不确定仅仅在C#编译器中是否可以轻松完成。我怀疑这是语言和CLR的限制。在CLR不支持的情况下,让它在C#中很好地工作可能很棘手。但是,是的,这是一个选择,而不是根本不可能。你比JS快了一分钟就找到了答案,他们都很简洁,有一些解释,所以我把这个标记为答案。谢谢