F# 如何在构造函数中引发异常?

F# 如何在构造函数中引发异常?,f#,F#,如果我这样做,难道没有意义吗 type Point = struct val Row: int val Column: int new (row, column) = if row >= 0 && column >= 0 then { Row = row; Column = column } else failwith "Cooridinators mu

如果我这样做,难道没有意义吗

type Point = 
    struct
        val Row: int
        val Column: int

        new (row, column) = if row >= 0 && column >= 0 then { Row = row; Column = column }
                            else failwith "Cooridinators must be non-negative!" 
        // This is not a valid object construction
        static member (+) (x: Point, y: Point) = Point (x.Row + y.Row, x.Column + y.Column)
        static member (-) (x: Point, y: Point) = Point (x.Row - y.Row, x.Column - y.Column)
        static member (*) (x: Point, a) = Point (x.Row * a, x.Column * a)
        static member (*) (a, x: Point) =  Point (x.Row * a, x.Column * a)
    end
如果它是一个类,那么也许我可以在
do
绑定期间引发异常,但是在一个结构中没有
do
,我应该怎么做

我发现有可能在
failwith
之后添加另一个构造函数来解决这个问题,但它提出了另一个问题,我如何调用隐式构造函数?我必须先明确地构造它吗

new () = { Row = 0; Column = 0} 
// Error structs auto supports a default constructor
如果我只是使用默认构造函数来实现这一点

new (row, column) = if row >= 0 && column >= 0 then { Row = row; Column = column }
                    else
                        failwith "Cooridinators must be non-negative!"
                        new Point () // error
在我看来,
Point()
返回的是一个单位,而不是
Point

我认为F编译器会抱怨,因为构造函数应该总是有一个结构:

新建(
模式
)=
表达式
{
初始化
}[然后
表达式
]

因此,初始化字段的部分不能嵌套在
if
下或任何其他表达式中。您可以在初始化之前或之后抛出异常(如果添加
然后
关键字)。(这对继承类很重要,但我认为这对结构没有任何影响。)

因此,编写代码的一种方法是:

type Point = 
    struct
        val Row: int
        val Column: int

        new (row, column) = 
          if row < 0 || column < 0 then failwith "Cooridinators must be non-negative!"
          { Row = row; Column = column }          

        // (Static members omitted)
    end
类型点=
结构
val行:int
val列:int
新建(行、列)=
如果行<0 | |列<0,则failwith“Cooridinator必须为非负!”
{行=行;列=列}
//(静态成员省略)
结束
请注意,我必须否定该条件,因为您需要在希望引发异常时指定大小写(而不是说何时可以构造对象)。另一种选择是:

new (row, column) = 
  { Row = row; Column = column }          
  then if row < 0 || column < 0 then failwith "Cooridinators must be non-negative!"
new(行、列)=
{行=行;列=列}
然后,如果行<0 | |列<0,则failwith“Cooridinator必须为非负!”

在初始化部分,您可以使用另一种方法抛出异常:

new(行、列)=
{Row=(如果Row<0 | | column<0,则failwith“Coordinators must non-negative!”;Row);
列=列}

请记住,验证结构构造函数并不总是一个好主意。正如您所发现的,您无法控制默认构造函数的初始化。如果它是一个类,您可以确保所有构造函数都按照您想要的方式进行验证。

这是一个老问题。然而,没有一个答案提到这一点:我认为惯用的F#way根本就不是抛出异常!为了实现这一点,您可以使用
静态成员tryCreate
,如果所有条件都满足,它将返回
某个点
,如果出现问题,则返回
。然后,您将遵循选项类型的轨迹来编写逻辑代码,而不是处理异常!我还认为F#record可能也是一种更为惯用的方式,除非您出于某些非常特定的目的明确地需要struct

new (row, column) = 
  { Row = ((if row < 0 || column < 0 then failwith "Coordinators must be non-negative!"); row); 
    Column = column }