Определить краткий класс F # с логикой пост-конструктора - PullRequest
2 голосов
/ 19 февраля 2010

Для этого определения класса:

type Foo(f1: int, f2: string) =
member x.F1 = f1
member x.F2 = PostProcess f2

Будет ли PostProcess (некоторая функция манипуляции со строками) вызываться каждый раз при доступе к f2?Если ответ - да, и я хочу избежать этого, какова правильная идиома?Это ниже рекомендуется?Это слишком многословно для меня.

type Foo =
val F1: int
val F2: string

new (f1, f2) as this = 
    {F1 = f1; F2 = f2;}
    then this.F2 = PostProcess(f2) |> ignore

Ответы [ 2 ]

6 голосов
/ 19 февраля 2010

В исходном определении F2 является свойством только для чтения, и функция PostProcess будет вызываться при каждом обращении к нему. Это легко проверить:

let PostProcess s = printfn "%s" s; s

type Foo(f1: int, f2: string) =
  member x.F1 = f1
  member x.F2 = PostProcess f2

let f = Foo(1,"test")
let s1 = f.F2
let s2 = f.F2

Вот как я написал бы класс для обработки только один раз:

type Foo(f1: int, f2: string) =
  let pf2 = PostProcess f2
  member x.F1 = f1
  member x.F2 = pf2
1 голос
/ 19 февраля 2010

Да, свойства пересматриваются каждый раз (например, как свойство get в C #).

См. Ответ @ kvb для краткого ответа на ваш конкретный вопрос.

В общем, см., Например,

http://msdn.microsoft.com/en-us/library/dd233192(VS.100).aspx

http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!894.entry

для получения языковой информации о лучшем способе написания конструкторов классов. Краткое описание заключается в том, что вы должны использовать «первичный конструктор» (как у вас есть, парены сразу после имени типа, которые принимают аргументы конструктора), а затем использовать let и do в верхней части класса в качестве конструктора корпус.

...