2016-06-29 2 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=...'

왜냐하면 변수는 이미 변경 가능하고 구조체는 컴파일되기 때문입니다. 내가 뭘 놓치고 있니?

편집

좋아, 나는 그것이 중요하지 않았다 생각했기 때문에 나는 나의 예를 단순화,하지만 난 지금이하는 것을 알 수있다. 사실 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 

편집 : 코멘트에서 언급 한 바와 같이 당신이 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 번호로 작업하는 경우, 당신은 수도 또한 돌연변이가 유일한 선택인지 다시 생각해보십시오. 의심 스럽습니다.

추신 : 한 나는 정의로, 나를 위해 완벽하게

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'가 struct 일 때만 변경 가능해야합니다. 클래스 인 경우 변수는 클래스의 인스턴스에 대한 참조를 보유하고 클래스의 속성이 수정 될 때 참조를 변경할 필요가 없습니다. 구조체에는 참조가 없으므로 데이터가 변수에 바로 저장되므로 구조체를 수정하면 변수를 수정한다는 의미이므로 변수 자체를 변경해야하는 이유입니다. –

관련 문제