2012-02-08 4 views
6

F#コードでいくつかのプロパティーを作成すると、私が知る限り、オートプロパティーはサポートされません。私は、バッキングフィールドを作成し、それらをヌルに初期化しなければなりません。これは、関数型プログラミングの用語では正しくないようです。例えば、F#プロパティーデザイン

 

let mutable albums : DbSet = null 
let mutable genres : DbSet = null

member x.Albums with get() = albums and set(value) = albums <- value member x.Genres with get() = genres and set (value) = genres <- value

これを行うには良い方法はありますか?。あなたの提案に感謝します。

+1

一つのこと - パッドのとTomasPetricekの優秀な答えに加えて:あなたは本当に「機能」になろうとしているならば、私はあなたがクラスを必要とする仮定やクラス - を調べます最初の場所でのような構造。自動プロパティは、特定のクラスの内部をアプリケーションの残りの部分に公開することによって、優れた情報隠蔽に違反します。アプリケーションの残りの部分に公開されているクラスの内部が必要な場合は、まずクラスを必要としないことがあります。私はあなたが本当に機能的にすべてがクラス内になければならないという考えを取り除くと思っていたいと思っていると言います。 –

+0

ああ、もう1つ - あなたが取り組んでいることを考えれば、このブログの投稿が役立つかもしれません。http://bugsquash.blogspot.com/2011/11/lenses-in-f.html –

答えて

10

F#が自動プロパティをサポートしていませんが、それは軽量な構文をサポートしています。これは、本質的にパッドによって提案されたレコードと同じである

type Music(genres : DbSet, albums : DbSet) = 
    member x.Albums = albums 
    member x.Genres = genres 

、あなたが持っているしたい場合は、より適切かもしれない:あなたは、いくつかの機能のコードを書いている場合は、実際にはより適切であるかもしれない読み取り専用プロパティを使用して、型の見え方(そしてC#やデータバインディングにどのように現れるか)をよりよく制御できます。

DbSetが変更可能なタイプの場合は、おそらく上記のタイプを使用して1回だけ初期化することができます(DbSetの値を変更することはできます)。 nullまたはF#でUnchecked.defaultOf<_>非常に悪い習慣と考えられているを使用して

member x.WithAlbums(newAlbums) = 
    Music(genres, newAlbums) 

、あなたは常に完全initlizedオブジェクトを作成しようとする必要があります:あなたはDbSet値を変更したい場合は、クローン化されたオブジェクトを返すメソッドを追加することができます。値が見つからない場合は、option型を使用して表現することができますが、プログラムを安全にするために、欠損値のハンドラを常に記述する必要があります。

+0

私はnullを使っていると思ったのは、この目的のためだけに明示的なOption型を持つ言語では良い練習とはみなせません。あなたの提案をありがとう。 – netmatrix01

+0

WPFは、明示的なNULLを優先するオプションタイプを受け入れますか? – Maslow

5

複雑なことをしない限り、クラスの代わりにレコードを使用することをお勧めします。不変性、構造的平等、パターンマッチングなど:

type Playlists = { 
    Albums: DbSet; 
    Genres: DbSet 
    } 

あなたが簡単にレコードのフィールドを取得することができます:基本的に、彼らは余分な機能を持つクラスでデフォルトレコードのフィールドに

let p = {Albums = ...; Genres = ...} 
let albums = p.Albums 
let genres = p.Genres 

は不変ですが。レコード内に可変フィールドを宣言することはできますが、悪い習慣とみなされます。プロパティを設定することはできませんが、古いレコードから新しいレコードを作成できます。推奨される明示的なパラメータで、このコンストラクタを使用して、

let p = {Albums = a; Genres = g} 

    // Create new records by updating one field 
    let p1 = {p with Albums = a1} 
    let p2 = {p with Genres = g2} 

あなたはクラスを作成するために主張する場合:デフォルトの不変性は、さらに、それは程度の理由コードは、より機能的かつ容易になり、通常は問題ではありません

type Playlists(a: DbSet, g: DbSet) = 
    let mutable albums = a 
    let mutable genres = g 
    // ... 

デフォルトコンストラクタを使用して、非NULL可能フィールドにUnchecked.default<'T>を使用するか、またはより自分の既定のコンストラクタを使用することができ、必要である:

// Set fields using dump values 
let mutable albums = new DbSet() 
let mutable genres = new DbSet() 

しかし、これらのフィールドを実際に使用する前に設定することを確認してください。あなただけ読み取り専用プロパティを必要とするとき、あなたが可変プロパティを必要とするとき

+0

レコードのフィールドを簡単な方法で変更することもできます。レコードにはいくつかの欠点もあります。たとえば、オブジェクトを構築するためには、すべてのフィールドの値を明示的に設定する必要があります。別の欠点は、レコードタイプが継承できず、派生することができないことです。 – ShdNx

+1

レコードには可変フィールドがあることは事実です。しかし、私はそれを悪いデザインと考えています。あなたがその方法で出るとき、クラスが優先されるべきです。 – pad

+0

あなたの提案に感謝します。たぶん私はレコードを使用するだろうが、私の場合、私はイムが財産にもっと興味を持っていると思う。しかし、私はあなたの提案について再考し、自分のタイプをレコードとして設計できるかどうかを確認します。 – netmatrix01

5

FYI - auto-propertiesはF#3.0向けに計画されています。 preview documentation [MSDN]を参照してください。あなたの例のように見えるになる:

type Music() = 
    member val Albums : DbSet = null with get, set 
    member val Genres : DbSet = null with get, set 
+0

明らかにこれらのものはプライベートにすることができません – Maslow

+0

'member val GroupBox1:GroupBox = new GroupBox()'は '追加情報:オブジェクトまたは値の初期化によってオブジェクトまたは値が完全に再帰的にアクセスされるこのコンストラクタは、オートプロパティのコンストラクタを保持するクラスの後に実行されるようです。 – Maslow

+0

もちろんです: 'member val private ...' – Daniel