1

Java 让我恼火的一件事是泛型类型参数的编译时翻译的糟糕实现。

我可以观察并理解 C# 实现要好得多,但我对它的工作原理感到困惑。

本质上,你怎么能说:

T t = new T()

如果您不知道 T 的类型,因此不知道构造函数参数要求?

我可以看到

Class<T> cl = T.class

或者

T[] tarr = new T[0]

但是如果您不知道构建它的要求,我看不出如何真正创建 T 的新实例?

4

4 回答 4

4

只有new T();当 T 被限制为具有普通的、无参数的公共构造函数时,您才能这样做,例如:

public class Foo<T> where T : new() {
    private myT = new T();
}

此外,无法指定是否存在任何其他类型的构造函数。这是不可能的:

// Doesn't work
public class Foo<T> where T : new(String, Int) {
    private myT = new T("Foo", 5);
}

对于您的其他观点,这是您在运行时获取 T 类型的方式:

var tType = typeof(T);

并且创建一个数组T实际上并不会创建任何实例(除非T是值类型,在这种情况下,它会创建该类型的默认值):

// Space for 32 T's, but nothing in the array.
// If T is a value type, like an int for instance, 
// each one would have the default value (0 for int, for example)
var arrayOfT = new T[32];
于 2012-06-04T18:50:52.120 回答
2

实际上,您要求编译器强制T使用无参数构造函数,以便他知道您可以new T()。例如:

class Test<T>
{
    T Create()
    {
        return new T();
    }
}

它不会编译,因为编译器不能确定它T不是一个抽象类并且它有一个默认的构造函数。为了使它起作用,你必须在 T 的真实类型上添加一个约束:

class Test<T> where T : new()

现在编译器将强制T成为具有默认构造函数的非抽象类。例如,此代码无效,因为给定类型是抽象的:

abstract class AnotherTest
{
    public void Test()
    {
        Test<Derived> test = new Test<Derived>();
    }
}

同样,如果您尝试使用没有默认构造函数的类,编译器将发出错误:

class AnotherTest
{
    public AnotherTest(string someParameter)
    {
    }

    public void Test()
    {
        Test<Derived> test = new Test<Derived>();
    }
}

对于数组,它有点不同。实际上,您只需要求编译器为给定数量的插槽保留内存,您不会为该对象分配内存(在引用类型的情况下,它只会放在null每个插槽中)。

MSDN 上的参考资料

于 2012-06-04T18:51:12.410 回答
2

你不能说new T()除非你使用约束来约束你的泛型类型有一个无参数的构造函数where T : new()——参见类型参数的约束

并且没有“构造函数参数要求”,因为唯一支持的构造函数是无参数构造函数。比如说,你不能使用new T(false)——形式的约束where T : new(bool)是不允许的。

于 2012-06-04T18:51:40.713 回答
0

new T()只是一个语法糖Activator.CreateInstance<T>()

于 2012-06-04T21:17:57.347 回答