移植!工作中

为了应用需要,KeiSystem 正在移植到 Java

从 C# 迁移到 Java 还是有不习惯的地方,虽然 C# 受到的最大批评就是“抄袭 Java”。看来 C# 还是相对优雅(如果 BCL 能小一点就好了)。话说从 VB .NET 扩展到 C# 的时候我也曾经觉得 VB .NET 好,所以当时的项目 C# 只用来处理 unchecked。现在我觉得 C# 如果写核心库不随便上 GUI 的话还是不错的,特别喜欢 uncheckedlockunsafe 的设计。

刚上手不习惯的有:

  • 没有 delegate,用内部类实现观察者模式实在是太不优雅了,而且 Callable 这种东西实现更困难了。
  • 所有自定义类型都是 class,而且只能传递引用副本,不存在 ValueType + ref。没有 struct 意味着用类似值类型的方法交互时要不断地 clone()
  • byte 是有符号的(陷阱!),所有基元数值类型都是有符号的(CLS 规定的值类型中,Byte 无符号,Int16/Int32/Int64 有符号,更符合习惯)。(注:SByteUInt16UInt32UInt64 虽然在 C# 和 VB .NET 中可用,但是不符合 CLS。)
  • 发生的异常未必是 throws 声明的,例如对 HttpExchangegetRequestHeaders() 进行 add() 实际上会触发 NotSupportedOperationException,但是 Headers 基类型没有显式抛出该异常。
  • 封装类型(Integer/Long etc)和基元数值类型(int/long etc)不等价,而且封装类型之间不存在继承。bencode 库中我修改了对整数的解析(从 IntegerLong,因为 BEncoding 规范是如此),但是运行报错不能将 Integer.valueOf() 的结果赋给 Long——直至我使用不怎么友善的 Number 类型作为赋值类型才正常。
  • 泛型类型擦除,都收缩到了 Object,再加上默认虚函数,导致
    • IEquatable<T> 这种接口实际上是不能实现的(IEquatable<T> 声明了一个 bool Equals(T) 的方法,C# 中通过自动插入类型+重载解决,Java 中会直接覆盖 Objectequals(Object));
    • 动态类型变长数组创建不可能,Array.newInstance() 需要传递一个 Class<?>,但是 T.class 非法,所以难以获得 T 的类型(Hibernate 中似乎有方案,不过对于现在的我来说太复杂)。

今天去审查,保安很和蔼,出来的时候还问事情办好了没有。

分享到 评论