在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
【C#泛型序列化困境】 问题的起因是这样,有一个需求,将JsonArray转化为List,JsonArray中的元素均是string,此string可被转化为int、float、或维持string。我的方案是扩展System.Collection.Generic.List<T>,实现一个void ParseFromJsonArray(JsonArray jsArray)方法,用于将JsonArray反序列为化List<T>。按此设计思路的代码应该像下面这样。 图一 然后使用上应该像下面这样,可以将一个array序列化为List。 图二 可上述看似良好的设计却无法实现,错误原因在于Add()方法。一个List<T>的Add方法实际上是Add<T>()。所以图1中的三个Add调用实际上是像下述这样的调用。 图三 编译器无法将Int、Float、String转化为T。所以上述代码无法编译通过。上述就是C#泛型坑爹之处,理论上对于List<int>调用ParseFromJsonArray,这是一个确定的类型List<int>,ParseFromJsonArray将JsonArray的内容解析为int即可,可编译器在编译ParseFromJsonArray时是在编译期,编译器只认T而对具体类型(运行时类型)int一无所知,而int无法转换为T从而导致编译错误。 所以上述设计的问题在于运行时需求与编译期行为的矛盾。如果这是C++,非常好解决,使用特化模板即可,针对int、float、string分别写一个特化函数,但是C#移除了C++中的特化模板语法,从而造成了本文的困境。 笔者也尝试了使用约束来解决,但很遗憾,在C#中 where T : int 也是个编译器错误。从而类似C++特化模板的方法也行不通了。 最后的结论,就是在目前的C#版本中,上述由List<T>来解析出具体类型从而Add()的功能无法实现。 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论