简体   繁体   English

C#如何执行运行时泛型?

[英]How does C# do runtime generics?

One thing that irritates me about Java is the awful implementation of compile-time translation of generic type arguments. 让我烦恼的是Java的糟糕实现,泛型类型实参的编译时转换。

I can observe and understand that the C# implementation is far better, but I'm confused as to how it works. 我可以观察并理解C#实现要好得多,但是我对它的工作方式感到困惑。

Essentially, how can you say: 本质上,您怎么说:

T t = new T()

If you don't know the type of T and therefore don't know the constructor argument requirements? 如果您不知道T的类型,因此不知道构造函数的参数要求?

I can see 我可以看到

Class<T> cl = T.class

or 要么

T[] tarr = new T[0]

but I don't see how you can really create a new instance of T if you don't know the requirements of constructing it? 但是,如果您不知道构造T的要求,那么我看不到如何真正创建T的新实例?

You can only do new T(); 您只能执行new T(); if T is constrained to have a plain, parameterless public constructor, for instance: 如果T被约束为具有一个普通的,无参数的公共构造函数,例如:

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

Additionally, there is no way to specify that any other sort of constructor exist. 此外,无法指定存在任何其他种类的构造函数。 This is not possible: 这是不可能的:

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

To your other points, this is how you get the type of T at runtime: 另外,这是在运行时获取T类型的方法:

var tType = typeof(T);

and creating an array of T doesn't actually create any instances (unless T is a value type, in which case it creates the default value of that type): 并且创建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];

Actually you ask the compiler to force T to have a parameterless constructor so he knows you can new T() . 实际上,您要求编译器强制T具有无参数的构造函数,以便他知道可以new T() For example: 例如:

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

It won't compile because the compiler can't be sure that T won't be an abstract class and that it'll have a default constructor. 它不会编译,因为编译器无法确定T不会是抽象类,并且不能拥有默认的构造函数。 To make it works you have to add a constrain on the real type of T: 为了使它起作用,您必须对T的实型添加一个约束:

class Test<T> where T : new()

Now the compiler will force T to be a non abstract class with a default constructor. 现在,编译器将强制T为具有默认构造函数的非抽象类。 For example this code is not valid because the given type is abstract: 例如,此代码无效,因为给定的类型是抽象的:

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

Again, if you try to use a class without default constructor the compiler will emit an error: 同样,如果您尝试使用没有默认构造函数的类,则编译器将发出错误:

class AnotherTest
{
    public AnotherTest(string someParameter)
    {
    }

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

With an array it's a little bit different. 与数组有点不同。 Actually you simply ask the compiler to reserve the memory for a given number of slots, you do not allocate the memory for that objects (in case of reference types it'll simply put null in each slot). 实际上,您只是简单地要求编译器为给定数量的插槽保留内存,而没有为该对象分配内存(对于引用类型,它只会在每个插槽中放入null )。

References on MSDN MSDN上的参考

You cannot say new T() unless you constrain your generic type to have a parameterless constructor using the where T : new() constraint — see Constraints on Type Parameters . 除非使用where T : new()约束将通用类型约束为具有无参数的构造函数,否则您不能说new T() -请参阅“类型参数的约束”

And there are no “constructor argument requirements”, since the only supported constructor is the parameterless one. 而且没有“构造函数参数要求”,因为唯一支持的构造函数是无参数构造函数。 You cannot use, say, new T(false) — constraints of the form where T : new(bool) are not allowed. 例如,您不能使用new T(false) -不允许where T : new(bool)的形式的约束where T : new(bool)

new T()仅仅是Activator.CreateInstance<T>()的语法糖

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM