如何使用F#中字符串类型的auto属性声明类?

时间:2017-08-30 14:48:40

标签: f# c#-to-f#

我很难理解如何在F#中定义类,其中我有没有声明值的属性。等同于c#代码的东西:

class Entity 
{
      public string Name { get; set; }
      public List<string> Favorites { get; set;}
}

我只能声明类型为

的类型
type Entity = 
    member val Name = "" with get, set

当我指定null时,Name的类型将为null。

3 个答案:

答案 0 :(得分:8)

正如评论中所提到的,F#中不建议使用null值,因此如果可以的话,最好避免使用它们。默认情况下,F#类型也不允许null,因此如果您使用的是不可变的F#list类型,那么最好的选择是将属性初始化为空列表:

type Entity() = 
    member val Name = "" with get, set
    member val Favorities : list<string> = [] with get, set

请注意,我添加了一个类型注释list<string>,因为编译器无法推断出空列表只包含代码中的字符串,否则最终会得到list<obj>

C#List类型在F#中缩写为ResizeArray,由于这是.NET类型,因此可以将此类型的属性初始化为null

type Entity() = 
    member val Name = "" with get, set
    member val Favorities : ResizeArray<string> = null with get, set

我想如果您使用一些非F#友好的ORM和类似的东西,这可能会有用,但是否则,使用它可能会给您带来很多痛苦和意外错误。

答案 1 :(得分:3)

与C#代码等效的最接近的F#是:

type Entity() = 
    member val Name = Unchecked.defaultof<string> with get, set
    member val Favorites = Unchecked.defaultof<string list> with get, set

然而,这是糟糕的F#,这就是为什么它有意设计看起来很难看。 F#不鼓励使用默认值,可空引用和变异。

因此,您应该决定一些合理的默认值:

type Entity() = 
    member val Name = "" with get, set
    member val Favorites = [] with get, set

或者您应该使用Option类型显式选择值,并使用None作为默认值,避免在运行时出现空引用异常:

type Entity() = 
    member val Name = None : string option with get, set
    member val Favorites = None : string list option with get, set

注意:我上面使用的list与C#List不同。

答案 2 :(得分:1)

我在您的评论中看到您使用member val的原因是针对Newtonsoft.Json。使用它与F#记录曾经是一个问题,但现在它完全正常。以下是用Newtonsoft.Json 10.0.3测试的:

type Foo =
    {
        x: int
        y: float
    }

open Newtonsoft.Json

let foo = JsonConvert.DeserializeObject<Foo>("{\"x\":1,\"y\":1.2}")
printfn "%A" foo
// {x = 1;
//  y = 1.2;}

对于需要默认构造函数和可变字段的序列化库,您可以将[<CLIMutable>]属性放在记录上,它将提供这些属性(但不能从F#中隐藏,以保证安全性。)