2016-06-29 21 views
1

私は次の構造体を作成してから、時刻と値のプロパティを変更して、変更可能な値x.Time_とx.Value_を変更します。私は、後のコードでセッターのいずれかを使用しようとすると、しかしF#変更可能な値は変更可能ではありません

type TimeDataPoint = 
    struct 
     val mutable private Time_: DateTime 
     val mutable private Value_: double 

     new (time: DateTime, value: double) = 
      { 
       Time_ = time 
       Value_ = value 
      } 

     member public x.Time 
      with get() = x.Time_ 
      and set(time: DateTime) = x.Time_ <- time 

     member public x.Value 
      with get() = x.Value_ 
      and set(value: double) = x.Value_ <- value 

    end 

、:

let tdp = TimeDataPoint(DateTime.Now, 0.0) 
tdp.Time <- DateTime.Now 

私はエラーを取得する:しても意味がありません

Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x=...'

私は変数が既に変更可能で、構造体がコンパイルされているからです。私は何が欠けていますか?

EDIT

[OK]を、私はそれは問題ではありませんでしたと思ったので、私は私の例を簡略化しますが、私は今、それがないことがわかります。私は実際にTimeDataPointsのLinkedListを持っています、そして、私はいくつかのノードの内容を変更しようとしていますので、提案したようにローカルに宣言することはできません。ここに私のコードは次のとおりです。

let myList = LinkedList<TimeDataPoint>() 
myList.AddFirst(TimeDataPoint(DateTime.Now, 0.0)) 
myList.First.Value.Value <- 1.0 

私はこの問題を回避するにはどうすればよいですか?

+0

作品、 'tdp'を' let mutable tdp = TimeDataPoint() 'とします。より多くの文脈を投稿できますか? –

+7

あなたの最善の選択肢は、このルートを下ることではありません。 .NETの構造体のデザインガイドラインでは、可変値型を避けることをお勧めします。https://msdn.microsoft.com/en-us/library/ms229031(v=vs.110).aspx変更可能な構造体を作ることで混乱の世界になります。https://blogs.msdn.microsoft.com/ericlippert/2008/05/14/mutating-readonly-structs/ – TheInnerLight

+0

意味があります。構造体を通常のクラスに変更しました。ありがとう。 – user3685285

答えて

3

tdpも変更可能にする必要があります。ストリップされたコードは以下の通りです。出力は

Ticks is 0 
Ticks is 636028131920527873 

となります。質問更新後

module Mutation 
open System 
type TimeDataPoint = 
    struct 
     val mutable private Time_: DateTime 
     new (time: DateTime) = 
      { 
       Time_ = time 
      } 
     member public x.Time 
      with get() = x.Time_ 
      and set(time: DateTime) = x.Time_ <- time 
    end 

let usingTdp() = 
    let mutable tdp = TimeDataPoint() 
    printfn "Ticks is %i" tdp.Time.Ticks 
    tdp.Time <- DateTime.Now 
    printfn "Ticks is %i" tdp.Time.Ticks 

EDIT:コメントで述べたように、あなたがstructである事を廃止すれば、すべては例えば、うまく動作します:

type TimeDataPoint = 
    val mutable private _v: int 
    new (v: int) = 
     { 
      _v = v 
     } 
    member public this.Value 
     with get() = this._v 
     and set(v: int) = this._v <- v 

let myList = LinkedList<TimeDataPoint>() 
myList.AddFirst(TimeDataPoint(1)) |> ignore 
myList.First.Value.Value <- 1 

のF#で作業する場合は、あなたがかもしれません突然変異が本当にあなたの唯一の選択かどうか再考することも考えてください。

PS:あなたが変異オブジェクトに固執することを決定した場合は、自動プロパティの構文を使用することを検討して、あなたがあなたのクラス定義を短縮することができます限り、私は定義として私のために完全によく

type TimeDataPoint(v, d) = 
    member val Value: int = v with get, set 
    member val Time: DateTime = d with get, set 
+0

申し訳ありませんが、私は私の質問を単純化しました。編集を参照してください。 – user3685285

+0

問題を完全に記入できますか? –

+0

'TimeDataPoint'が格納される変数は、' TimeDataPoint'が構造体であるときに変更可能である必要があります。それがクラスの場合、変数はクラスのインスタンスへの参照を保持し、クラスのプロパティが変更されたときに参照を変更する必要はありません。構造体には参照がなく、データは変数のすぐそこに格納されているので、構造体を変更するということは変数を変更することを意味します。そのため、変数自体を変更可能にする必要があります。 –