在构造期间以递归方式访问的对象

时间:2017-09-11 15:21:39

标签: constructor f#

考虑这四种类型

  type UninitializableType =
    val initialhashcode: int
    new () as newobj =
      { initialhashcode= newobj.GetHashCode () }

  type Parent =
    val mutable initialhashcode: int
    new () as parent =
      { initialhashcode= 0 } then
      do parent.initialhashcode <- parent.GetHashCode ()

  type ChildA =
    inherit Parent
    new () =
      { inherit Parent () }

  type ChildB =
    inherit Parent
    new () =
      { inherit Parent () }
    override child.GetHashCode () = 666

所有四种类型在编译时都是明确定义的。但是,其中一些类型无法初始化。

第一个UninitializableType,是我想做的简化示例。我在构造函数表达式中使用newobj,因此构造函数在运行时失败并不奇怪。

第二个是Parent,是一种解决方法。它与UninitializableType几乎相同,但它有一个可行的构造函数,这样我就可以创建“父母”。对象。到目前为止,非常好。

第三个ChildA也有效。它似乎是无辜的,但事实是它不会失败,一旦我进一步绊倒了我(见下文)。

最后一个,ChildB,是邪恶的。尽管乍一看它看起来与ChildA非常相似,但它的构造函数失败了。从技术上讲,运行ChildB.GetHashCode ()访问未完成的对象。

目前我正在考虑如何解决这个问题。你们当中有没有一个优雅的解决方案呢?

编辑:

这个问题很难回答,因为我没有告诉我最终目标是什么。 (对TheQuickBrownFox的道具,它没有阻止他在这个主题上发表两个好的提示/技巧)。

我的目标是有两种类型,Parent和Child,每种都有一个默认构造函数(意思是不带任何参数的实例构造函数)。 Child类型应该继承Parent,对于这个例子,让我们说类型Parent继承System.Object。

我想在Parent的实现中尽可能多地进行初始化,但仍允许Child提供与初始化相关的一些细节。这个想法是Child的实现应该尽可能简单。我想Child的实现可以使用我喜欢的参数显式调用辅助Parent构造函数 - 这对我来说感觉很尴尬。

1 个答案:

答案 0 :(得分:3)

我不清楚你要做什么。如果你想要的是存储初始哈希码,而覆盖GetHashCode()你可以这样做:

type MyType private (initialHashCode) =
  inherit obj()
  new () = MyType(base.GetHashCode())
  member __.InitialHashCode = initialHashCode
  override __.GetHashCode() = 0

let x = MyType()
x.InitialHashCode // 8628710
x.GetHashCode() // 0