理解F#类型构造函数

And*_*dry 8 .net syntax f# constructor

我正在尝试创建一个复杂的类型,并在构建时需要执行一些操作.所以我开始编写代码:

type public MyType =
   val private myvar: int
   val private myvar2: string
   (* ...Some val declarations... *)
   new () = {
      (* The default ctor makes something *)
   }
   new (ctorpar: AnotherType) = {
      myvar = 1;
      myvar2 = "Hello";
      (* Other assignments in the form var = val *)
      (* Here I would like to start a cycle in order *)
      for i in ctorpar.array do
         (* Do something *) (* ERROR *)
   }
Run Code Online (Sandbox Code Playgroud)

好吧,当尝试从一个赋值中放置一个for或者其他东西时,编译器会发疯.我假设如下:new的语法遵循计算表达式之一,或者更好,新的是计算表达式(我暗示这是因为大括号和从一个oinstruction到另一个oinstruction的分号).在这种情况下,对于构造函数计算表达式,可以仅进行分配.

那么请你能回答我:

1)我的演绎是否正确?(关于计算表达式和类型的构造函数).

2)如果我需要在构造函数中放置一组明确的指令,我该怎么办?嗯,你知道,有时需要在施工时执行一个动作,它可能涉及从周期到所有可能性的所有事情.

但无论如何编译器都生气了......

感谢kvd我明白我有可能做到以下几点:

type public MyType =
   val private myvar: int
   val private myvar2: string
   (* ...Some val declarations... *)
   new () = {
      (* The default ctor makes something *)
   }
   new (ctorpar: AnotherType) = 
      for i in ctorpar.ACollection do
         (* Something *)
      {
      myvar = 1;
      myvar2 = "Hello";
      }
Run Code Online (Sandbox Code Playgroud)

我很抱歉,但这对我没有帮助,因为F#编译器告诉我这个:

在构造对象初始化之前,对象构造函数不能直接使用try/with和try/finally.这包括构造函数,例如'for x in ...',可以详细说明这些构造的使用.这是Common IL强加的限制.

好的,如果问题是在对象初始化之前做了一些事情,并且听起来是正确的,那么让我们在以下情况之后执行以下操作:

type public MyType =
   val mutable private myvar: int
   val mutable private myvar2: string
   (* ...Some val declarations... *)
   new () = {
      (* The default ctor makes something *)
   }
   new (ctorpar: AnotherType) = 
      {
      myvar = 1;
      myvar2 = "Hello";
      }
      then
      for i in ctorpar.ACollection do
         (* Something *)
         myvar <- 10
Run Code Online (Sandbox Code Playgroud)

失败再次感到沮丧:

未定义值或构造函数"myvar".

我该怎么办????似乎之后,它不识别我班级中的元素,它似乎是正确的,因为它需要一个标识符,就像在使用self或this声明成员时...在这里它没有自我引用,并且正确地告诉我:"你想要得到的东西我不能给你!!!!!!"

kvb*_*kvb 13

  1. 不,你的推论是不正确的.花括号更像是一个记录构造表达式,它只能包含字段赋值. 除了为大括号内的每个字段赋值之外,您无法执行任何操作.

  2. 你可以在正常分配之前(即在开始大括号之前)放置语句.如果您希望之后执行其他语句,则需要使用以下then关键字:

    type public MyType =
      val private myvar: int
      val private myvar2: string
    
      new () = 
        for i in 1 .. 10 do
          printfn "Before field assignments %i" i
        { myvar = 1; myvar2 = "test" } 
        then 
          for i in 1 .. 10 do
            printfn "After field assignments %i" i
    
    Run Code Online (Sandbox Code Playgroud)

编辑

关于你的新问题,你可以使用new (ctorpar:AnotherType) as this = ...然后this.myvar <- 10.


Tom*_*cek 10

kvb的答案很棒,并为您提供了所要求的所有信息:-).

我只是建议使用隐式语法,其中主要构造函数紧跟在类型名称后面.这使得很多事情变得容易:

type MyType(n:int, s:string) =
  do 
    // Run before fields initialized (they aren't accessible here)
    for i in 1 .. 10 do
      printfn "Before field assignments %i" i
  // Initialize fields (accessible from now on)
  let myvar = n
  let myvar2 = s
  do // Run after fields initialized - you can use them here
     for i in 1 .. 10 do
       printfn "After field assignments %i" i

  // You can add multiple constructors too:
  new() = MyType(0, "hi")
  member x.Foo = 0
Run Code Online (Sandbox Code Playgroud)

  • 的确,请参阅http://lorgonblog.wordpress.com/2009/02/13/the-basic-syntax-of-f-classes-interfaces-and-members/ (2认同)