Hide this comment

Note that .Net defines the obj.ReferenceEquals static method:

[link:msdn.microsoft.com]

By on 6/20/2009 11:31 PM ()Reply
Hide this comment

The JIT does not reliably inline obj.ReferenceEquals and when it inlines obj.ReferenceEquals it generates suboptimal machine code, so LanguagePrimitives.PhysicalEquality should generally be preferred.

[Update: As Don points out below, PhysicalEquality actually does what I was looking for in a previous version of this post. Somehow I completely missed that.]

By on 6/21/2009 2:17 AM ()Reply
Hide this comment

The F# name for the PowerPack operator (==) is LanguagePrimitives.PhysicalEquality, e.g.

let r1 = ref 1

let r2 = ref 1

let x = LanguagePrimitives.PhysicalEquality r1 r2

The semantic definition for the operator is

let PhysicalEqualityObj (xobj:obj) (yobj:obj) =

objEq xobj yobj

|| (match xobj with

| null -> false

| :? System.ValueType -> xobj.Equals(yobj)

| _ -> false)

where "objEq" is the ceq instruction. This is optimized to simply "ceq" when semantically possible - basically for static application to any reference type that is not System.Object, System.ValueType or System.Enum.

The function is not at all efficient when aplied to value types, and it is likely we will restrict its use to reference types through a constraint.

Kind regards

don

By on 6/21/2009 10:43 AM ()Reply
Hide this comment

Thanks for the explanation, Don. Somehow I completely missed that a call to PhysicalEquality gets expanded inline.

By on 6/21/2009 11:10 AM ()Reply
Hide this comment

For completeness I should add that the function is efficient for all primitive value types, through the use of the following static optimizations in FSharp.Core.dll

when 'T : bool = (# "ceq" x y : bool #)

when 'T : int = (# "ceq" x y : bool #)

when 'T : sbyte = (# "ceq" x y : bool #)

when 'T : int16 = (# "ceq" x y : bool #)

when 'T : int32 = (# "ceq" x y : bool #)

when 'T : int64 = (# "ceq" x y : bool #)

when 'T : byte = (# "ceq" x y : bool #)

when 'T : uint16 = (# "ceq" x y : bool #)

when 'T : uint32 = (# "ceq" x y : bool #)

when 'T : uint64 = (# "ceq" x y : bool #)

when 'T : float = (# "ceq" x y : bool #)

when 'T : char = (# "ceq" x y : bool #)

However these are semantically equal to the "=" operator, whose use would be normally be preferred.

don

By on 6/21/2009 10:52 AM ()Reply
Hide this comment

Thanks for all the replies - all fixed now.

Why all the mystery around this operation? - certainly seems like == should be available in the core libs, with perhaps a compiler warning to "please use =" if == is used on privitive types. (Or even a warning all the time w/o a nowarn that says "are you sure you didn't mean = for structural equality?"

BTW, is there any way to "cast away" structural equality and statically cast each side to an object where = is the same as ==? (This was one of my attempts - but I don't think I got it work.) The proposed solutions are of course better, but just for my own edification.

thanks

By on 6/21/2009 1:56 PM ()Reply
Hide this comment

In principle we could give "==" this meaning by default in F#.

However many F# users have to routinely port code from C# (e.g. MSDN samples). Here "==" has a very different meaning (typically aligning with "=" in F#), and so it is very important to have people think twice when using this operator.

thanks

don

By on 6/22/2009 4:51 AM ()Reply
Hide this comment

Really? Except for strings, which are a (reasonable) special case, I didn't think anyone would overload == to do more than a pointer compare on reference types. Oh well, no accounting for taste then :) (Unless I'm missing some included overloads of == in the standard libs. that I never realized.)

By on 6/22/2009 7:14 AM ()Reply
Hide this comment

You're right that' it's not used that often. However looking through mscorlib, here are some examples of reference types with overloaded ==

System.Version

System.Security.Principal.SecurityIdentifier

System.Security.AccessControl.GenericAce

System.Security.Principal.SecurityIdentifier

System.Security.Principal.IdentityReference

System.Uri

System.Security.Cryptography.BigInt (private :-) )

Kind regards

Don

By on 6/25/2009 2:28 PM ()Reply
Hide this comment

A few others would include System.Xml.Linq.XName and System.Xml.Linq.XNamespace. In addition, IIRC, all Reflection types (Assembly,Type, MethodInfo etc) have operators == and != overloaded.

By on 6/25/2009 2:48 PM ()Reply
Hide this comment

Hi,

I didn't check, but I believe you can find the operator in the PowerPack, for Caml-compatibility.

This comparison function is also defined in the core library. You define the operator yourself:

let (==) = LanguagePrimitives.PhysicalEquality

Laurent.

By on 6/20/2009 2:47 PM ()Reply
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper

Logging in...