特定のケースでコンパイラがこの警告を発する理由を実際に説明することはできません。コンパイラはおそらく過度に慎重であるため、無視しても問題ないという@ildjarnに同意します。
ただし、警告が実際に何かが期待どおりに進まない可能性があるという有用なヒントを与える可能性がある例を示すことができます。このようなミュータブルがある場合struct
:
[<Struct>]
type Test =
val mutable ticks : int64
member x.Inc() = x.ticks <- x.ticks + 1L
new (init) = { ticks = init }
ここで、Inc
メソッドは構造体を変更します(また、変更可能なフィールドにアクセスすることもできますticks
)。Test
値を作成してそれを変更する関数を書いてみることができます。
let foo () =
let t = Test(1L)
t.Inc() // Warning: The value has been copied to ensure the original is not mutated
t
t
ローカル値をとしてマークしなかったmutable
ため、コンパイラは、を呼び出すときに値が変更されていないことを確認しようとしますInc
。値を変更するかどうかはわからないInc
ため、安全なのはコピーを作成することだけです-したがってfoo
、値を返しますTest(1L)
。
t
としてマークを付けるとmutable
、コンパイラは呼び出しの結果としてそれを変更することを心配する必要がないため、警告を表示しません(そして関数は戻りますTest(2L)
):
let foo () =
let mutable t = Test(1L)
t.Inc()
t
ただし、例の警告の原因はよくわかりません。おそらく、コンパイラーは(いくつかの中間表現の結果として)Ticks
操作が左側の値(System.DateTime.Now
およびt
それぞれ)を変更する可能性があると考えており、それを防ぎたいと考えています。
奇妙なことに、F#で独自の構造体を作成すると、変数を(私が期待するものです)としてDateTime
マークしない限り、どちらの場合も警告が表示されますが、標準での動作は異なります。したがって、おそらくコンパイラは、私が欠落している標準型について何かを知っています...t
mutable
DateTime