2016-08-30 12 views
22

एफ # = ऑपरेटर है, जो लगभग हमेशा तुम क्या चाहते के लिए संरचनात्मक समानता का उपयोग करता है:मैं एफ # में संदर्भ समानता की जांच कैसे करूं?

let a = [1; 2; 3] 
let b = [1; 2; 3] 
printfn "%A" (a = b) // Prints "true" 

लेकिन कुछ एल्गोरिदम में, यह पूछने के लिए "सक्षम होने के लिए महत्वपूर्ण हो सकता है इन दो चीजों हैं एक ही वस्तु ? " यह ग्राफ में चक्रों का पता लगाने में मदद कर सकता है, उदाहरण के लिए। तो मैं एफ # में संदर्भ समानता के लिए कैसे पूछूं? यानी, मैं नीचे isSameObject फ़ंक्शन कैसे लिखूं?

let isSameObject x y = ??? 
let a = [1; 2; 3] 
let b = [1; 2; 3] 
let a' = a 
printfn "%A" (isSameObject a b) // Prints "false" 
printfn "%A" (isSameObject a a') // Prints "true" 

उत्तर

34

जवाब है, यह पता चला है, उपयोग करने के लिए है LanguagePrimitives.PhysicalEquality:

let isSameObject = LanguagePrimitives.PhysicalEquality 
let a = [1; 2; 3] 
let b = [1; 2; 3] 
let a' = a 
printfn "%A" (isSameObject a b) // Prints "false" 
printfn "%A" (isSameObject a a') // Prints "true" 

ठीक एक सवाल मैं स्टैक ओवरफ़्लो पर मिल सकता है कि इस बारे में पूछा गया था: short-cutting equality checking in F#? और उस प्रश्न के विषय के बाद से लगभग मुझे ठीक पहले देखा, मुझे लगा कि मैं फिर से सवाल पूछूंगा (और जवाब दूंगा)। उम्मीद है कि इस प्रश्न की विषय पंक्ति "F # में संदर्भित समानता" जैसे शब्दों के लिए Googling को खोजना आसान बनाती है।

obj.ReferenceEquals के बारे में क्या?

एक टिप्पणी में, फ्योडोर सोइकिन पूछता है कि obj.ReferenceEquals के साथ क्या गलत है। जवाब है, "बहुत ज्यादा नहीं" है, लेकिन वहाँ के दो तरीके हैं, जिसमें LanguagePrimitives.PhysicalEquality सबसे एफ # कोड के लिए की तुलना में बेहतर obj.ReferenceEquals है: obj.ReferenceEquals सिर्फ दो obj लेता है

1) PhysicalEquality फेंकता एक संकलक त्रुटि जब आप इसे दो अलग अलग प्रकार से पारित

let a = [1;2;3] 
let b = ['a';'b';'c'] 

obj.ReferenceEquals(a,b) // Returns false 
LanguagePrimitives.PhysicalEquality a b // Compiler error 

2) PhysicalEquality आप मूल्य प्रकार, केवल संदर्भ के प्रकार की तुलना नहीं दूँगी: रों और इसलिए खुशी से तुलना करने के लिए एक int listchar list की कोशिश करता है। obj.ReferenceEquals आपको दो मान प्रकारों की तुलना करने देगा, और निश्चित रूप से उन्हें पहले बॉक्स करेगा। लेकिन यह बॉक्स से हर एक अलग है, जिसका अर्थ है कि यह होगा हमेशा वापसी झूठी यहाँ तक कि जब आप इसे "एक ही" मूल्य वस्तु दिया:

let n = 3 
let n' = n 
obj.ReferenceEquals(n,n') // Returns false! 
LanguagePrimitives.PhysicalEquality n n' // Compiler error 

और, ज़ाहिर है, वहाँ एक अन्य अंतर है, जो व्यक्तिगत करने पर निर्भर करता है वरीयता और आसानी से उपयोग। PhysicalEquality करी-शैली पैरामीटर लेता है, जो प्रकार अनुमान और आंशिक अनुप्रयोग के साथ अच्छी तरह से खेलता है। obj.ReferenceEquals tupled-style पैरामीटर लेता है, जिसका अर्थ है कि यह उपयोग करने के लिए थोड़ा उलझन में है।

इन सभी कारणों से, LanguagePrimitives.PhysicalEquality उपयोग करने के लिए, लगभग हर स्थिति में, obj.ReferenceEquals से बेहतर है।

+3

अच्छे पुराने 'obj.ReferenceEquals' के साथ कुछ भी गलत है? –

+0

@FyodorSoikin - मैंने आपके प्रश्न के जवाब में दो टिप्पणियां लिखीं, फिर एहसास हुआ कि वे कोड उदाहरणों के साथ उत्तर में बेहतर होंगे। तो आप वहां जाते हैं: 'obj.ReferenceEquals' ** खराब नहीं है **, लेकिन' PhysicalEquality' बेहतर है क्योंकि यदि आप दो अलग-अलग प्रकारों की तुलना करने का प्रयास करते हैं तो यह आपको त्रुटियों को टाइप करेगा। (जो आपके कोड में लगभग निश्चित रूप से एक बग है, और आप इसे पकड़ने में मदद करने के लिए * कंपाइलर चाहते हैं)। – rmunn

संबंधित मुद्दे