是否可以在Scala中实现不使用反射的`??`(来自C#的空合并运算符)?

TN.*_*TN. 6 reflection scala null-coalescing-operator structural-typing

我在某处发现了C#null coalescing operator'??'的实现:

implicit def coalescingOperator[T](pred: T) = new {
  def ??[A >: T](alt: =>A) = if (pred == null) alt else pred
}
Run Code Online (Sandbox Code Playgroud)

然后可以像使用a ?? b哪种方式一样使用它if (a == null) b else a.

在反编译类文件后,我看到它生成带反射的代码(在Scala 2.8.1中).

为什么它会生成反射,是否可以修改该代码,以免产生反射?

Rex*_*err 12

Scala与Java没有相同的匿名类概念.如果你说的话

new {
  def fish = "Tuna"
}
Run Code Online (Sandbox Code Playgroud)

那么它会将新方法的所有用法解释为需要结构类型,即相同的

def[T <: {def fish: String}](t: T) = t.fish
Run Code Online (Sandbox Code Playgroud)

因为没有共同的超类,所以需要使用反射.我不知道为什么会这样; 这对性能来说完全是错误的,通常不是你需要的.

无论如何,修复很简单:创建一个实际的类,而不是匿名的类.

class NullCoalescer[T](pred: T) {
  def ??[A >: T](alt: => A) = if (pred == null) alt else pred
}
implicit def anyoneCanCoalesce[T](pred: T) = new NullCoalescer(pred)
Run Code Online (Sandbox Code Playgroud)

在2.10中,它仍然可以做出可以说是错误的事情,但是(1)它会向你发出警告,以这种方式使用反射(所以至少你会知道它何时发生),除非你关闭它们,并且(2)你可以使用较短的版本implicit class /* blah blah */并跳过implicit def只添加样板的版本.