当前位置: 首页 > 编程语言 > C#

为什么这个泛型在编译时没有解析?分享

时间:2023-04-10 22:12:56 C#

为什么这个泛型在编译时没有解析?我有以下代码。我希望它打印:ABCDONE而不是它打印PPPDONE为什么?更新我不是在寻求解决方案。我想知道为什么会这样。我认为泛型是在编译时解决的。据我所知,它应该能够在编译时正确解决这些问题,但显然不能,我也不明白为什么。我正在寻找原因的解释,而不是解决方案。这是代码:usingSystem;使用System.Collections.Generic;使用System.Linq;使用系统文本;namespaceConsoleApplication50{classParent{publicstringFieldName{get;放;}公共字符串ID{得到;放;}}classChildA:Parent{publicstringFieldValue{get;放;}}classChildB:Parent{publicDateTime?开始{得到;放;公共日期时间?结束{得到;放;}}classChildC:Parent{publicICollectionValues{get;放;}}classProgram{voidValidate(Parentitem)whereT:Parent{if(itemisT)Validate(itemasT);}voidValidate(ChildAfilter){Console.WriteLine("A");}voidValidate(ChildBfilter){Console.WriteLine("B");}voidValidate(ChildCfilter){Console.WriteLine("C");}voidValidate(Parentfilter){Console.WriteLine("P");//什么都不做占位符所以代码会编译}ArgumentExceptionFail(Parentfilter,stringmessage){returnnewArgumentException(message,filter.FieldName);}voidRun(){变量列表=新列表{newChildA(),newChildB(),newChildC()};验证(列表[0]);验证(列表[1]);验证(列表[2]);}publicstaticvoidMain(){newProgram().Run();控制台.WriteLine();Console.WriteLine("完成");控制台.ReadLine();}}}泛型是一个运行时概念,这是它们与C++模板的主要联系。不同之处在于,C++模板是一个编译时概念。在Validate方法中,T在编译时始终是未知的,即使调用者明确指定也是如此。Validate对T的唯一了解是它来自Parent。更具体地说,泛型不能用于生成代码。您尝试在C++下工作,因为当C++看到对Validate的调用时,它实际上会重新编译Validate,因此模板成为一种代码生成。在C#下,Validate只编译一次,所以泛型不能作为一种代码生成。在C++下,对Validate的调用将在编译时实例化模板。在C#下,对Validate的调用将在运行时实例化泛型方法。重载解析是在编译时执行的,而不是运行时。通常的解决方案是在这里使用一个简单的虚拟调度:classParent{publicvirtualvoidValidate(){Console.WriteLine("P");}}classChildA:Parent{publicoverridevoidValidate(){Console.WriteLine("A");}}classChildB:Parent{publicoverridevoidValidate(){Console.WriteLine("B");}}voidRun(){varlist=newList{newChildA(),newChildB()};列表[0].验证();//打印“A”列表[1].Validate();//打印“B”}该项目将始终作为父类型进行验证。泛型背后的想法是你没有类型特定的代码..因此它的“通用”部分。您将限制为该类的一个分支,在本例中为Parent及其后代的所有内容。这意味着代码应该像传入的对象是Parent类型一样执行。正如dtb所说,访问者模式可以在这里应用。另一个想法是简单地拥有一个定义每个类都必须支持的Validate()方法的接口。我认为这是一个更好的选择。假设您可以访问C#4.0,您可以使用“dynamic”关键字打破C#编译器将执行的静态重载解析。只需将验证函数更改为:voidValidate(Parentitem)whereT:Parent{dynamicdyn=item;如果(项目是T)验证(动态);}输出将是:C:tmp>temp.exeABCDONE我刚刚从@juharr到EricLippert博客的链接中了解到这一点。在msdn上阅读有关动态类型的更多信息。以上就是C#学习教程:这个泛型为什么在编译时没有解析?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: