我正在阅读Herbert Schildt的C#完整参考书.他说,关于泛型,那
只有一个泛型类的版本可以处理type参数是引用类型的所有情况.这是因为所有引用的大小(以字节为单位)是相同的.因此,只需要一个版本来处理所有类型的引用.这种优化还可以减少代码膨胀.
有人可以解释为什么所有引用类型只有一个版本的泛型类?C#如何仅使用一个版本进行管理?例如:在值类型的情况下,本书说,C#为Generic<int>和创建一个单独的类Generic<double>.那么,为什么它不为Generic<MyClass>和创建单独的类Generic<AnotherClass>?什么没有创建-seperate类的泛型引用类型与类的大小(如文中所述)?
首先,正如我在评论中所说:获得一本更好的书.
其次,您需要了解如何为泛型生成代码.C#编译器为每个泛型类生成IL - 一种"中间语言",而IL与原始源代码一样,是真正通用的.在运行时,抖动("及时"编译器)为您调用的每个方法生成机器代码 ; 它将IL转换为您正在运行的任何机器的代码.
假设您有一个带有方法的泛型类:
class C<T>
{
public static T[] One(T item)
{
return new T[] { item };
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,无论T在运行时是什么,都知道此方法是类型安全的.
当您调用C<string>.One("hello");jitter生成代码以创建一个字符串引用的数组时,将给定的字符串引用复制到数组的第一个位置,并返回对该数组的引用.
现在假设你打电话C<string>.One("goodbye").抖动不需要重新生成代码,因为它已经在内存中有机器代码.
现在,如果你打电话C<Task<Giraffe>>.One(giraffeTask),抖动又不需要重新生成代码,因为它已经在记忆的方法,创建了一个数组引用大小的东西,复制引用中item的数组,并返回到阵列的参考.无处 - 除了T []创建 - 该方法使用的事实是T实际上是一个字符串或实际上是产生长颈鹿的任务.如果我们确保数组构造也并不需要知道是什么类型的优势-何必呢? - 然后我们就可以重新使用生成的代码了.
但是我们无法逃避重新使用为调用C<int>.One时生成的代码C<double>.One,因为第一个将4字节整数复制到数组中; 第二个复制8字节双.抖动可以通过占用额外的空间来制作两个略有不同版本的机器代码,从而更好地优化代码.
此优化是一个实现细节,但它是有助于了解的细节之一,因为它为您提供了一个良好的心理模型,说明该功能如何工作,为什么它以这种方式工作,以及它与不同语言中的类似功能的区别.Java(带有擦除)和C++(带有模板)与C#的真正的运行时泛型类型系统略有不同,这会导致语义和性能差异.
| 归档时间: |
|
| 查看次数: |
237 次 |
| 最近记录: |