【问题标题】:Is inline and override possible in F#? What are the alternatives?在 F# 中是否可以内联和覆盖?有哪些替代方案?
【发布时间】:2020-02-03 16:08:18
【问题描述】:

假设我有一个像这样的通用记录结构:

[<Struct>]
type Container<'t when 't : (member ToString : Unit -> string) > =
  {
    Item : 't
  }
  with
    member inline this.ToString () =
      sprintf "(%s)" (this.Item.ToString ())

这会给出一个编译警告:

这个新成员隐藏了抽象成员“System.Object.ToString() : string”。重命名成员或改用“覆盖”。

但是如果我切换到override 我得到一个错误:

[<Struct>]
type Container<'t when 't : (member ToString : Unit -> string) > =
  {
    Item : 't
  }
  with
    override inline this.ToString () =
      sprintf "(%s)" (this.Item.ToString ())

此成员、函数或值声明不得声明为“内联”

如果我删除 inline,我会收到一个新错误:

[<Struct>]
type Container<'t when 't : (member ToString : Unit -> string) > =
  {
    Item : 't
  }
  with
    member this.ToString () =
      sprintf "(%s)" (this.Item.ToString ())

此代码不够通用。 ^t : (member ToString : ^t -> string) 时的类型变量 ^t 无法泛化,因为它会超出其范围。

我应该如何在 F# 中实现这一点?

【问题讨论】:

  • 接受警告?
  • @RobertHarvey 我想我可以,虽然我希望这在没有警告的情况下以某种方式成为可能
  • robkuz.github.io/Decoupling-Strategies-I 似乎对这些错误提供了一些见解。
  • 为什么需要member ToString : Unit -&gt; string 约束?无论如何,每个对象都有这样的方法。
  • @FyodorSoikin 你是对的。我正在尝试解决这个错误,我认为这两种方式都没有影响

标签: generics f#


【解决方案1】:

您不能在同一个成员上具有覆盖和内联,因为覆盖需要方法“存在”才能覆盖 CLR 中的基类。

话虽如此,您可以使用%O 来简化此操作:

[<Struct>]
type Container<'t> =
  {
    Item : 't
  }
  with
    override this.ToString () =
      sprintf "(%O)" this.Item

话虽如此,如果您删除约束,这也适用于 %s 和 ToString:

[<Struct>]
type Container<'t> =
  {
    Item : 't
  }
  with
    override this.ToString () =
      sprintf "(%s)" (this.Item.ToString ())

【讨论】:

  • 为什么会这样?拥有ToString 的约束不是总是满足的吗?
  • @sdgfsdh 通用方法约束是静态解析的,并且仅适用于内联。你不能有内联,所以你得到一个错误。它总是工作(如你所见)没有约束,所以你可以把它排除在外。
猜你喜欢
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多