F#中的静态构造函数-它们何时运行? [英] Static constructors in F# - when do they run?

查看:94
本文介绍了F#中的静态构造函数-它们何时运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试各种在F#中创建单例的方式,以便更好地理解其细微之处.我不知道F#中的单例模式是否曾经有用,但我想尝试一下.我对一个涉及这些单例实例的静态构造函数的结果感到惊讶.首先,我将向您展示我的代码,然后将进一步介绍我的问题.

I am experimenting with various ways of creating singletons in F#, so that I understand the subtleties better. I don't know if the singleton pattern is ever useful in F#, but I wanted to experiment. And I was surprised by one result involving static constructors on those singleton instances. First I'll show you my code, and then I'll go into more details about my question.

在一个名为TrySingleton的项目中,我创建了三个模块.这是Eager.fs:

In one project called TrySingleton, I created three modules. Here's Eager.fs:

module TrySingleton.Eager

type EagerClass() =
    do
        printfn "Initializing eager class..."

    static do
        printfn "Static constructor of eager class"

let Instance = EagerClass()

这里是Lazy.fs:

module TrySingleton.Lazy

type LazyClass() =
    do
        printfn "Initializing lazy class..."

    static do
        printfn "Static constructor of lazy class"

let Instance = lazy LazyClass()

这是我在Main.fs中称呼它们的方式:

And here's how I call them, in Main.fs:

module TrySingleton.Main

[<EntryPoint>]
let main argv =
    printfn "Starting main with args %A" argv
    printfn "Accessing eager instance:"
    printfn "%A" Eager.Instance
    printfn "Accessing lazy instance:"
    printfn "%A" Lazy.Instance.Value
    printfn "Accessing eager instance again:"
    printfn "%A" Eager.Instance
    printfn "Accessing lazy instance again:"
    printfn "%A" Lazy.Instance.Value
    printfn "Success; exiting."
    0

我期望Eager类的静态构造函数在程序启动时立即运行,并且不确定Lazy类的静态构造函数何时运行.但是,这是我得到的输出:

I was expecting the static constructor of the Eager class to run immediately on program startup, and wasn't sure when the Lazy class's static constructor would run. However, here's the output I got:

Starting main with args [||]
Accessing eager instance:
Static constructor of eager class
Initializing eager class...
TrySingleton.Eager+EagerClass
Accessing lazy instance:
Static constructor of lazy class
Initializing lazy class...
TrySingleton.Lazy+LazyClass
Accessing eager instance again:
TrySingleton.Eager+EagerClass
Accessing lazy instance again:
TrySingleton.Lazy+LazyClass
Success; exiting.

Eager类似乎不像我想的那样渴望.它的静态构造函数仅在我尝试访问该实例时才运行,而我认为静态类构造函数将在程序启动时运行.

It seems that the Eager class is not as eager as I thought it would be. Its static constructor was only run the first time I tried to access the instance, whereas I thought that the static class constructors would run at program startup time.

我想我只剩下一个问题了,除了问:这是否在任何地方都有记录?我错过了什么文档,这些文档谈论何时将运行类的静态构造函数?

I guess I don't have much of a question left, except to ask: is this documented anywhere? What documentation did I miss that talks about when static constructors of a class will be run?

推荐答案

我设法在F#官方文档中找到了答案,我很少再看了,因为 http://fsharpforfunandprofit.com 就是这样一个很好的资源.但是说(强调我的意思):

I managed to find the answer in the official F# documentation, which I rarely look at anymore because http://fsharpforfunandprofit.com is such a great resource. But the Constructors article in the official F# documentation says (emphasis mine):

除了指定用于创建对象的代码外,还可以在执行首次使用该类型在类型级别上执行初始化的类类型中创建静态letdo绑定.

In addition to specifying code for creating objects, static let and do bindings can be authored in class types that execute before the type is first used to perform initialization at the type level.

有指向类中的let绑定 do类中的绑定文章,其中说(再次强调我的意思):

There are followup links to the let Bindings in Classes and do Bindings in Classes articles, which say (emphasis mine, again):

静态let绑定是该类的静态初始化程序的一部分,可以保证在首次使用该类型之前执行.

Static let bindings are part of the static initializer for the class, which is guaranteed to execute before the type is first used.

在构造对象时,类定义中的do绑定将执行操作,对于静态do绑定,在第一次使用类型时,将执行 .

A do binding in a class definition performs actions when the object is constructed or, for a static do binding, when the type is first used.

因此,看来我可以回答自己的问题:答案是我最初的期望是错误的.静态构造函数不一定会在程序启动时运行,而是仅在首次使用该类时才运行.这意味着,如果您在两个不同的类中使用Singleton模式,其中一个依赖于另一个类,则它们的构造函数(和静态构造函数)将按照给定依赖性的顺序运行. (当然,在这种情况下,可能会有更好,更实用的方法来设计代码;我将其用作说明,而不是对该设计的认可.)

So it looks like I can answer my own question: the answer is that my initial expectations were wrong. The static constructor will not necessarily be run at program startup time, but only when that class is first used. Which means that if you're using the Singleton pattern in two different classes, one of which depends on the other, their constructors (and static constructors) will be run in the order that makes sense given the dependency. (Of course, there might be better, more functional ways to design your code in that scenario; I use it as an illustration rather than as an endorsement of that design.)

这篇关于F#中的静态构造函数-它们何时运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆