Byref、ref、およびbyrefの理解 &
-
14-11-2019 - |
質問
まあ、私はF#が参照(参照のようなある種のC++)を管理できることを理解するようになりました。これにより、関数で渡されたパラメータの値を変更する可能性が可能になり、プログラマは複数の値を返すこともできます。しかし、ここに私が知る必要があるものがあります:
Refキーワード:キーワード
ref
値から、推論された型のその値への参照を作成するために使用されます。だからlet myref = ref 10
これは、F#が型のオブジェクトを作成することを意味します
Ref<int>
そこに置く(可変フィールドに)私のint 10
.わかっただから私はそれを前提としています
ref
のインスタンスを作成するために使用されますRef<'a>
タイプ。それは正しいですか?アクセス値:参照に格納されている値にアクセスするために、私はこれを行うことができます:
let myref = ref 10 let myval = myref.Value let myval2 = !myref
一方、
:=
演算子はちょうど私がこのような値を編集することができます:let myref = ref 10 myref.Value <- 30 myref := 40
だから
!
(バン)私の参照を逆参照します。と:=
それを編集します。これも正しいと思います。演算子(&):この演算子は何をしますか?参照型に適用されますか?いいえ、私はそれが変更可能な値に適用されなければならないと思います、そしてこれは何を返しますか?参考にしてみませんか?住所は?対話型を使用している場合:
let mutable mutvar = 10;; &a;;
最後の行はエラーをスローするので、私は何を理解していません
&
演算子はのためのものです。ByRef:何について
byref
?それは私にとって非常に重要ですが、私はそれを理解していないことを認識しています。私はそれがパラメータの受け渡しに関して関数で使われていることを理解しています。渡された値を編集できるようにするには、byrefを使用します(これは関数型言語の哲学に少し反していますが、f#はそれ以上のものです)。次のことを考えてみましょう:let myfunc (x: int byref) = x <- x + 10
これは奇妙です。私はあなたが参照を持っている場合ことを知っています
let myref = ref 10
次に、これを実行して値を編集します:myref <- 10
このようにする必要があるため、エラーが発生します:myref := 10
.しかし、その関数で私が編集できるという事実x
を使用して、<-
演算子とは、x
参照ではありませんよね?私がそれを仮定した場合
x
は参照ではありませんが、関数では、次を使用するときにも想定していますbyref
パラメーターでは、そのパラメーターに変更可能な構文を適用できます。だから、私がこれを私が大丈夫だと仮定すれば、それは構文の問題です、そして、実際には、すべてがうまくいきます(コンパイラエラーはありません)。しかし、何ですかx
?関数の呼び出し:Byrefパラメータを利用した関数を使用するにはどうすればよいですか?
ザ-
&
オペレーターが関与していますが、これをよりよく説明できますか?この記事の内容: MSDNのパラメータと引数 次の例を示します:type Incrementor(z) = member this.Increment(i : int byref) = i <- i + z let incrementor = new Incrementor(1) let mutable x = 10 // A: Not recommended: Does not actually increment the variable. (Me: why?) incrementor.Increment(ref x) // Prints 10. printfn "%d" x let mutable y = 10 incrementor.Increment(&y) (* Me: & what does it return? *) // Prints 11. printfn "%d" y let refInt = ref 10 incrementor.Increment(refInt) (* Why does it not work in A, but here it does? *) // Prints 11. printfn "%d" !refInt
解決
Refキーワード はい、あなたが書くとき let a = ref 10
あなたは本質的に書いています let a = new Ref<int>(10)
ここで、 Ref<T>
型には可変フィールドがあります Value
.
アクセス値 ザ- :=
と !
演算子は書くための単なるショートカットです:
a.Value <- 10 // same as writing: a := 10
a.Value // same as writing: !a
ByRef メソッドパラメータでのみ(合理的に)使用できる特別な型です。これは、引数が本質的に(ヒープまたはスタックに割り当てられた)いくつかのメモリ位置へのポインタであるべきであることを意味します。それはに対応します out
と ref
c#の修飾子。この型のローカル変数は作成できないことに注意してください。
演算子(&) を期待する関数/メソッドに引数として渡すことができる値(ポインタ)を作成する方法です byref
タイプ。
関数の呼び出し との例 byref
ローカルの可変変数への参照をメソッドに渡しているために機能します。参照を介して、メソッドはその変数に格納されている値を変更できます。
以下は動作しません:
let a = 10 // Note: You don't even need 'mutable' here
bar.Increment(ref a)
その理由は、次の新しいインスタンスを作成しているためです Ref<int>
そして、あなたはの値をコピーしています a
このインスタンスに。ザ- Increment
メソッドは、次のインスタンスのヒープに格納されている値を変更します Ref<int>
, 、しかし、あなたはもうこのオブジェクトへの参照を持っていません。
let a = ref 10
bar.Increment(a)
これは動作します。 a
型の値です Ref<int>
そして、ヒープに割り当てられたインスタンスへのポインタを渡しています Increment
そして、ヒープ割り当てされた参照セルから値を取得します !a
.
(以下を使用して作成された値を使用できます ref
の引数として byref
コンパイラはこのケースを特別に処理するので、自動的に参照を取ります Value
これは便利なシナリオであるため、フィールド。..).