Подтвердить что ты не робот

Когда следует использовать let, member val и member this.?

F # имеет множество различных способов определения переменных/членов в типах. Когда следует использовать let, member val и member this. в F #, и в чем разница между ними? Как насчет статических и изменяемых элементов?

4b9b3361

Ответ 1

Ответ от @meziantou уже дает хороший обзор вариантов (и как они ведут себя по-другому), поэтому позвольте мне просто дать краткий обзор или список рекомендаций:

  • Используйте let или let mutable, если вы хотите определить локальное значение, которое отображается только внутри типа (по существу, это поле private или функция private).

  • Вы можете использовать val или val mutable для определения открытого поля, но я бы не рекомендовал это, если вам действительно не нужно публичное поле (например, для некоторой библиотеки .NET требуется тип с этой структурой).

  • Использование member x.Foo = ... - лучший способ открыть (только для чтения) состояние из типа. Большинство типов F # неизменяемы, поэтому это, пожалуй, самый общий публичный элемент.

  • Использование member x.Foo with get() = .. and set(value) ... полезно, когда вам нужно создать свойство get/set со своим собственным кодом в getter и setter. Иногда это полезно, когда вы создаете изменяемый объект.

  • Использование member val Foo = ... with get, set - это в основном то же самое, что и автоматически реализованные свойства в С#. Это полезно, если вам нужно свойство mutable с getter и setter, которые просто читают/записывают изменяемое поле поддержки.

Ответ 2

Мне стало проще просто декомпилировать, что происходит, поэтому:

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

на самом деле следующее:

public class Region
{
    internal float t;

    internal float [email protected];

    internal float [email protected];

    public float Width
    {
        get
        {
            return [email protected];
        }
    }

    public float Height
    {
        get
        {
            return 0f;
        }
    }

    public float Left
    {
        get
        {
            return [email protected];
        }
        set
        {
            [email protected] = value;
        }
    }

    public float Top
    {
        get
        {
            return 0f;
        }
        set
        {
            this.t = value;
        }
    }

    public Region() : this()
    {
        this.t = 0f;
        [email protected] = 0f;
        [email protected] = 0f;
    }
}

Ответ 3

Этот пример объясняет разницу между синтаксисами:

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