2012-02-08 5 views
6

तो जब कभी भी मेरे एफ # कोड में कुछ गुण बना रहा हूं, क्योंकि एफ # ऑटो गुणों का समर्थन नहीं करता है, जहां तक ​​मुझे पता है। मुझे बैकिंग फ़ील्ड बनाना है और उन्हें शून्य पर प्रारंभ करना है, जो कार्यात्मक प्रोग्रामिंग शब्दों में सही नहीं लगता है। उदाहरण के लिएएफ # गुण डिजाइन

 

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

ओह और एक और बात - जो आप काम कर रहे हैं उसे देखते हुए, आपको यह ब्लॉग पोस्टिंग सहायक मिल सकता है: http://bugsquash.blogspot.com/2011/11/lenses-in-f.html –

उत्तर

10

एफ # ऑटो गुण का समर्थन नहीं करता है, लेकिन यह एक हल्के वाक्य रचना का समर्थन करता है जब तुम सिर्फ एक केवल पढ़ने के लिए संपत्ति की जरूरत है। आप कुछ कार्यात्मक कोड लिख रहे हैं, तो का उपयोग कर केवल पढ़ने के लिए गुण वास्तव में अधिक उपयुक्त हो सकता है:

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

यह अनिवार्य रूप से पैड द्वारा सुझाए गए रिकॉर्ड के रूप में एक ही है, लेकिन यह अधिक उपयुक्त है अगर आप करना चाहते हो सकता है प्रकार कैसे दिखते हैं (और वे सी # में कैसे दिखाई देते हैं, या डेटा बाध्यकारी के लिए) पर बेहतर नियंत्रण।

यदि DbSet एक उत्परिवर्तनीय प्रकार है, तो आप शायद उपरोक्त प्रकार का उपयोग कर सकते हैं और इसे केवल एक बार शुरू कर सकते हैं (आप अभी भी DbSet मानों को संशोधित करने में सक्षम होंगे)। आप DbSet मूल्य में परिवर्तन करना चाहते हैं, तो आप एक विधि है कि एक क्लोन ऑब्जेक्ट जोड़ सकते हैं:

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

null या एफ # में Unchecked.defaultOf<_> एक बहुत बुरा व्यवहार माना जाता है का उपयोग करना है और आप हमेशा पूरी तरह से initlized वस्तु बनाने के लिए प्रयास करना चाहिए। यदि मान गुम हो सकता है, तो आप इसका प्रतिनिधित्व करने के लिए option प्रकार का उपयोग कर सकते हैं, लेकिन फिर आपको अपने प्रोग्राम को सुरक्षित बनाने के लिए हमेशा लापता मूल्य के लिए हैंडलर लिखना होगा।

+0

कि मैंने जो कुछ भी नल का उपयोग करके सोचा था उसे किसी ऐसी भाषा में एक अच्छा अभ्यास नहीं माना जा सकता है जिसमें इस उद्देश्य के लिए स्पष्ट विकल्प प्रकार हैं। आपके सुझावों के लिए धन्यवाद। – netmatrix01

+0

क्या WPF स्पष्ट नल के पक्ष में विकल्प प्रकार स्वीकार करता है? – 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 
    // ... 

जब एक डिफ़ॉल्ट निर्माता के लिए आवश्यक है, तो आप गैर नल क्षेत्रों के लिए 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

एफवाईआई - एफ-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

'सदस्य वैल समूहबॉक्स 1: ग्रुपबॉक्स = नया ग्रुपबॉक्स() 'कहता है' अतिरिक्त जानकारी: ऑब्जेक्ट या वैल्यू के प्रारंभिकरण के परिणामस्वरूप ऑब्जेक्ट या वैल्यू को पूरी तरह से पहले से एक्सेस किया जा रहा है प्रारंभिक। 'यह कन्स्ट्रक्टर ऑटो-प्रॉपर्टी के कन्स्ट्रक्टर वाले वर्ग के बाद दौड़ने लगता है। – Maslow

+0

निश्चित रूप से वे हैं: 'सदस्य मूल्य निजी ...' – Daniel