10

に固執しrecordたいのですが、に戻りたくありませんobject。だから私はのを作ることが可能かどうか疑問に思っていfieldますrecord privateか?またはのを作成しprivate memberますrecord。他のconcrete typesようなものはdiscriminated unionどうですか?

または、この要件は言語仕様に違反していますか?

4

3 に答える 3

16

いいえ、単一のフィールドを非公開にすることはできません:http: //msdn.microsoft.com/en-us/library/dd233184

ただし、すべてのフィールドをプライベートにし、プロパティを介して選択したフィールドを公開することができます。'フィールドはプライベートであるため、レコードのインスタンスを作成するには、Create関数が必要になることに注意してください。

type MyRec = 
    private
        { a : int
          b : int }
    member x.A = x.a
    member private x.Both = x.a + x.b  // Members can be private
    static member CreateMyRec(a, b) = { a = a; b = b }

MyRec.Both上記のプロパティの場合のように、メンバーはプライベートにすることができます。

編集:上記は、フィールドをMyRecにプライベートではなく、MyRecが定義されているモジュールにプライベートにします。F#レコードのフィールドがプライベートとして宣言されている場合の奇妙なアクセシビリティスコープに対するダニエルの回答を参照してください。

于 2012-09-12T13:58:05.970 に答える
12

この要件の問題は、レコードの言語機能ではプロパティがパブリックである必要があることです。たとえば、プロパティと書き込みを含むr型のレコードがある場合、コンパイラはそれをに変換します。RNameAge
{ r with Age = 20 }new R(r.Name, 20)

アイデアは、withすべてのプロパティ(変更するプロパティを除く)をコピーするため、それらにアクセスできる必要があるということです。このため、コンパイラーは実際にあらゆる用途のメソッドを生成できwithますが、それによって多くのメソッドが生成される可能性があります。

レコードを好む理由は何ですか?それらには2つの優れた機能があります-withキーワード(privateとにかくメンバーで失う)と構造的同等性(同じ値を持つ場合、2つのインスタンスは同じです)。それとは別に、いくつかのフィールドを非表示にしたい場合は、クラスの方が使いやすいようです。

これは簡単な例です(構造的平等を実装していません):

type R(name:string, age:int) = 
  member x.Name = name
  member x.WithAge(newAge) = R(name, newAge)

フィールドでレコードを使用privateすることは問題ないようですが、実装ファイル内でパブリックフィールドを使用し、すべての外部ユーザーのフィールドを非表示にするF#署名ファイルを使用する方が理にかなっている場合があります。このようwithにして、実装のように機能を使用できますが、タイプは非表示になります。

于 2012-09-12T14:13:44.000 に答える
1

それは不可能だと思います。MSDNによると:

レコードフィールドは、プロパティとして自動的に公開され、レコードの作成とコピーに使用されるという点でクラスとは異なります。レコードの構築もクラスの構築とは異なります。レコードタイプでは、コンストラクターを定義できません。

「自動的に公開される」はあなたの質問に答えるための鍵です。新しいタイプを作成したくない理由は3つありますか?

于 2012-09-12T13:48:55.413 に答える