使用F#继承null引用异常

时间:2013-05-03 18:17:11

标签: inheritance f# nullreferenceexception

有没有办法让以下代码有效?

open System.Collections.Generic

type Geometry<'t>(child: 't) =
  let values = List()
  member o.add (v: float) = values.Add v; child

and Line() as self =
  inherit Geometry<Line>(self)
  member o.length v = o.add v

let line = Line().length(50.0)

我得到了

  

System.NullReferenceException:未将对象引用设置为对象的实例。

编辑:

调用以下内容触发异常就足够了。

let line = Line()

动机是你可以做到例如:

let line = Line().x1(10).y1(20).x2(30).y2(10).color("blue") // ...

你可以在所有几何中重复使用普通成员(圆形,椭圆形......)

3 个答案:

答案 0 :(得分:5)

open System.Collections.Generic

type Geometry<'t when 't :> Geometry<'t>>() =
  let values = List()
  member o.add (v: float) = values.Add v; o :?> 't

and Line() =
  inherit Geometry<Line>()
  member o.length v = o.add v

let line = Line().length(50.0)

答案 1 :(得分:3)

在.NET(以及扩展名为F#)中,您需要初始化一个对象,然后才能调用它上面的任何方法或将其传递给另一个方法。因此,在将对象传递给基础构造函数Line之前,需要初始化<{1}}对象。但是在调用基础构造函数之前无法对其进行初始化,因此没有直接的方法来执行您想要的操作。

话虽如此,F#有一个系统可以在定义之前捕获非法递归使用值,所以我很惊讶你没有得到更有意义的异常,而不是Geometry<Line>(self)(或者更好的是,编译时错误)。比较一下,如果您尝试使用以下定义调用NullReferenceException会发生什么:

new Rec()

解决这个问题的一种方法是使用懒惰来延迟使用type Rec(r:Rec) = new() as self = Rec(self) 标识符:

self

可悲的是,这不起作用,进一步证实了在这种情况下检查初始化稳健性存在F#错误的理论。幸运的是,这可以通过使用type Geometry<'t>(child: Lazy<'t>) = let values = List() member o.add (v: float) = values.Add v; child.Value and Line() as self = inherit Geometry<Line>(lazy self) member o.length v = o.add v 的显式构造函数而不是主构造函数来解决:

Line

答案 2 :(得分:1)

有关F#的一点需要注意 - 它的一个主要特点是它非常简洁(特别是与C#或Java相比)。但是,根据我的经验,尝试使代码尽可能简洁,也很容易被人带走;相反,你最好的目的是编写像实用一样简洁的代码。

我提出这个问题的原因是因为你使用分号将多个语句放在一行上 - 它通过保存一个或两个新行来缩短代码,但缺点是它不能很好地与VS调试器。

如果删除分号的使用,您应该能够在有问题的行上放置断点,然后使用VS调试器(或MonoDevelop / Xamarin Studio)逐步执行它们。明确知道哪个语句会导致抛出异常,因此更容易确定问题的原因。

如果您尝试此操作并且能够识别相关行,请将该信息添加到您的问题中,我们将能够为您提供更好的答案。

type Geometry<'t> (child: 't) =
  let values = ResizeArray ()
  member o.add (v: float) =
    values.Add v
    child

and Line () as self =
  inherit Geometry<Line> (self)
  member o.length v =
    o.add v

let line =
    let l = Line ()
    l.length 50.0