【问题标题】:Access member of outer type from inner type从内部类型访问外部类型的成员
【发布时间】:2018-06-26 13:01:32
【问题描述】:

我想知道我必须做什么才能编译以下 F# 代码:

type MyType() =
  [<Literal>]
  let outer = "Foo"

  type MyInnerType() =
    [<Literal>]
    let inner = outer + ".Bar"

编译器引发错误 FS0039“未定义值或构造函数‘外部’”。这是不可能的还是设计不允许的?

我想在 xUnit 测试方法的属性中使用这些值,该方法要求这些值是编译时常量(因此 [&lt;Literal&gt;]):

    [<Trait("", inner)>]
    [<Fact>]
    let test() =
      Assert.Equal(3, 1 + 2)

【问题讨论】:

  • MyInnerType 看不到outer 的原因是编译器实际上将outer 视为MyType 的构造函数中的局部变量,因此,在IL 中生成时,outer 绑定甚至不存在。由于MyType 中没有对绑定的引用,因此它被完全优化掉了。如果你在MyType 中有一个引用outer 的属性或方法,那么outer 的值将被直接复制到该属性或方法中,但实际的绑定仍然会被删除。
  • 另外需要注意的是,仅仅将MyInnerType 类标识为MyType 的成员并不能使其成为F# 中的内部类。 F# 不支持嵌套类。
  • @AaronM.Eshbach 有没有办法让outer public 而不是private
  • 你能把你的文字放在一个模块中而不是放在类中吗?
  • 自从我了解到 F# 不支持嵌套类,我可以用模块来实现它。

标签: f# xunit


【解决方案1】:

可能对您有用的是跨 F# modules 工作的文字表达式。下面的sn-p

module A =
    [<Literal>]
    let A = "A"

    module B =
        [<Literal>]
        let B = A + "B"

[<Literal>]
let C = A.A + A.B.B + "C"

fsi 消耗为

module A = begin
  val A : string = "A"
  module B = begin
    val B : string = "AB"
  end
end
val C : string = "AABC"

这意味着 F# 编译器乐于将来自不同模块(可能是嵌套的)的文字和常量表达式组合成一个常量表达式。

【讨论】:

  • 模块可以嵌套,这样我就可以省略A.,只在模块Z嵌套到模块A中写入A
  • @David 是的,它们可以这样嵌套。我已经修改了我的 sn-p 来展示这种组合。
【解决方案2】:

我假设外部是一个类字段,所以你需要在引用它的内部之前实例化这个类。

这可能对你有用:

type MyType() =
  static member outer = "Foo"

  type MyInnerType() =
    let inner = MyType.outer + "Bar"

【讨论】:

  • 我希望 outer 成为用 C# 编写的 const string outer,因此是静态成员。
猜你喜欢
  • 1970-01-01
  • 2013-10-21
  • 2019-09-03
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 2015-04-20
相关资源
最近更新 更多