为什么构造函数中不允许使用类型参数
本文关键字:类型参数 不允许 构造函数 为什么 | 更新日期: 2023-09-27 18:33:47
有方法的类型参数。为什么构造函数没有类型参数?
例
我认为有几个(不是很多(例子会很有用。我目前的问题如下:
internal class ClassA
{
private readonly Delegate _delegate;
public ClassA<T>(Func<T> func)
{
_delegate = func;
}
}
一Delegate
对我的班级来说就足够了。但是要将其作为方法组传递,我需要将参数定义为Func<T>
。
阅读 C# 规范后,它确实有意义,但可能会令人困惑。
每个类都有一个关联的实例类型,对于泛型类声明,实例类型是通过从类型声明创建构造类型来形成的,每个提供的类型参数都是相应的类型参数。
class C<T>
{
}
C<T>
是构造类型,实例类型将通过使用类型参数构造类型的过程创建。
C<String> c = new C<String>();
编译器采用构造的类型C<T>
,并使用提供的类型参数创建C<String>
的实例类型。泛型只是一个编译时构造,一切都在运行时以封闭构造类型的方式执行。
现在让我们回答您的问题并在这里进行测试。
class C
{
public C<T>()
{
}
}
这是不可能的,因为您正在尝试构造一个不存在的类型。
C c = new C<String>();
C
和C<String>
之间的implicit
或explicit
转换是什么?没有。这甚至没有意义。
由于此示例中的C
是非泛型类型,因此实例类型是类声明本身。那么,您期望C<String>
如何构建C
?
您要执行的操作的正确声明是这样的。
internal class Class<T>
{
private readonly Delegate _delegate;
public Class(Func<T> function)
{
_delegate = function;
}
}
这里因为我们有一个构造的类型Class<T>
,编译器可以创建正确的实例类型。
Func<String> function = new Func<String>(() => { return String.Empty; });
Class<String> c = new Class<String>(function);
如果您尝试在问题中按照您想要的方式进行操作。
Func<String> function = new Func<String>(() => { return String.Empty; });
Class c = new Class<String>(function);
构造类型将是Class<String>
,这与类型C
不同,并且没有implicit
或explicit
转换。如果编译器允许这样做,C
将处于某种未知和不可用的状态。
关于构造类型,你需要知道的是这个。
class C<T>
{
public C<T>()
{
}
}
虽然不能显式声明泛型构造函数,但它是有效的,但只能在运行时作为封闭类型构造函数。
C<String> c = new C<String>();
在编译时,将创建以下构造函数。
public C<String>()
{
}
这就是为什么这是有效的:
C<String> c = new C<String>(); // We just used the closed type constructor
如果你想要的东西被允许,这样的事情可能会发生。
class C<T>
{
public C<U>()
{
}
}
// ???
C<String> c = new C<Int32>();
您现在可以看到如果允许构造将出现的问题。希望这能提供一些见解,规范相当长,并且有很多许多部分涵盖了泛型、类型参数、构造类型、封闭和开放类型、绑定和未绑定。
这可能会变得非常混乱,但编译器规则不允许这样做是一件好事。
他们根本没有包含该功能,可能是假设它不是很有用。
如果构造函数需要它,则整个类型可能需要它。但是在你不这样做的情况下,你可能仍然可以使用Object。
如果你不能...是的,我认为没有太多办法绕过它,对不起。:''你可以使用反射,但当然那会慢得离谱......或者,您可以玩动态生成方法的技巧,根据您的用例,这可能是值得的,但也可能很慢(它至少增加了 1 个额外的间接调用(。
因为构造函数是类的一部分,因此类型参数可能属于整个类型。
如果可以选择在构造泛型类的实例时使用不同的类型参数,那么您实际上是在构造不同类型的类。我知道它与C++中的模板化类不同,但概念是相似的。
要解决您的特定问题,您可以使用"模板化"工厂方法。
可以传入委托,而不是强类型的 Func
class Program {
static void Main(string[] args) {
Func<int> i = () => 10;
var a1 = new ClassA(i);
Func<string> s = () => "Hi there";
var a2 = new ClassA(s);
}
}
internal class ClassA {
private readonly Delegate _delegate;
public ClassA(Delegate func) { // just pass in a delegate instead of Func<T>
_delegate = func;
}
}
因为您可以通过将类声明为泛型来实现这一点
internal class ClassA<T>
{
private readonly Delegate _delegate;
public ClassA(Func<T> func)
{
_delegate = func;
}
}
那么你将隐式拥有一个泛型结构