F# 我应该在什么时候使用let、member val和member this。?

F# 我应该在什么时候使用let、member val和member this。?,f#,F#,F#有许多不同的方法来定义类型中的变量/成员。什么时候应该在F#中使用let、member val和member this.,它们之间有什么区别?静态成员和可变成员如何?此示例解释了语法之间的差异: type MyClass() = let random = new System.Random() [<DefaultValue>] val mutable field : int member val AutoProperty = random.Next()

F#有许多不同的方法来定义类型中的变量/成员。什么时候应该在F#中使用
let
member val
member this.
,它们之间有什么区别?静态成员和可变成员如何?

此示例解释了语法之间的差异:

type MyClass() =
    let random  = new System.Random() 
    [<DefaultValue>] val mutable field : int
    member val AutoProperty = random.Next() with get, set
    member this.ExplicitProperty = random.Next()

let c = new MyClass()
// c.random is not accessible
c.field <- 42 // 'field' is accessible

// An automatic property is only evaluated upon initialization, and not every time the property is accessed
printfn "AutoProperty = %d" c.AutoProperty // x
printfn "AutoProperty = %d" c.AutoProperty // Still x

// The value of the explicit property is evaluated each time
printfn "ExplicitProperty = %d" c.ExplicitProperty // y
printfn "ExplicitProperty = %d" c.ExplicitProperty // The value is re-evaluated so you'll get a different value
type MyClass()=
让random=newsystem.random()
[]val可变字段:int
成员val AutoProperty=random.Next()和get,set
成员this.ExplicitProperty=random.Next()
设c=newmyclass()
//c.不可访问

c、 field来自@meziantou的答案已经很好地概括了这些选项(以及它们的不同行为),所以让我简单总结一下,或者列出一些建议:

  • 如果要定义仅在类型中可见的局部值(基本上是
    private
    字段或
    private
    函数),请使用
    let
    let mutable
    。在顶层模块中,这些模块可以公开访问并进行一次评估<代码>让模块级别的可变
创建一个没有支持值的可写字段

  • 您可以使用
    val
    创建自动属性,它是
    member val Foo=。。使用get
    。从F#开始,这被视为一个字段,但它在内部实现为一个get属性,带有一个支持字段,以防止突变

  • 您可以使用
    val mutable
    定义公共字段,但我不建议这样做,除非您确实需要公共字段(例如,某些.NET库可能需要具有此结构的类型)

  • 使用
    成员x.Foo=…
    是从类型公开(只读)状态的最佳方法。大多数F#类型是不可变的,因此这可能是最常见的公共成员。它是仅获取实例属性的缩写

  • 使用带有get()的
    成员x.Foo=。。和set(value).
    在需要使用gettor和settor中的自定义代码创建get/set属性时非常有用。这在创建可变对象时有时很有用

  • 使用
    成员val Foo=。。。使用get时,set与C#中自动实现的属性基本相同。如果您需要一个具有getter和setter的可变属性,而getter和setter只是读取/写入可变的支持字段,那么这非常有用

  • 在类型上使用
    static let
    创建一个静态(类级别)只读字段,该字段在内部创建一个带有支持字段的属性。使用
    static mutable let…
    读取/写入静态字段(无支持字段)

  • 使用
    static val mutable private
    创建一个带有支持字段的静态读/写自动属性,它不能是公共的


  • 我发现反编译正在发生的事情更容易,所以:

    type Region() =
      let mutable t = 0.0f
      member val Width = 0.0f
      member x.Height = 0.0f
      member val Left = 0.0f with get,set
      member x.Top with get() = 0.0f and set(value) = t <- value
    

    val mutable
    member val…以及get、set
    之间有什么区别?它像
    intx
    vs
    int x{get;set;}
    在C#?
    val
    创建字段时,
    member val
    创建属性。是否可以使用扩展自动属性?@Maslow需要向现有类型添加新字段,这是不可能的。
    public class Region
    {
        internal float t;
    
        internal float Width@;
    
        internal float Left@;
    
        public float Width
        {
            get
            {
                return this.Width@;
            }
        }
    
        public float Height
        {
            get
            {
                return 0f;
            }
        }
    
        public float Left
        {
            get
            {
                return this.Left@;
            }
            set
            {
                this.Left@ = value;
            }
        }
    
        public float Top
        {
            get
            {
                return 0f;
            }
            set
            {
                this.t = value;
            }
        }
    
        public Region() : this()
        {
            this.t = 0f;
            this.Width@ = 0f;
            this.Left@ = 0f;
        }
    }