op_Equality (== Operator) for Value-Types

  • Thread starter MasterGaurav \(www.edujini-labs.com\)
  • Start date
M

MasterGaurav \(www.edujini-labs.com\)

Hi,

I have a, probably very basic, query on value-types.

Why cannot I use the == operator directly for value-types (not primitive
types like int, float, double etc)? Why do I need to either have an implicit
operator (to type-cast to primitive type) or override/overlaod the ==
operator myself?




--
Happy Hacking,
Gaurav Vaish | www.mastergaurav.com
www.edujini-labs.com
http://eduzine.edujini-labs.com
-----------------------------------------
 
C

Chris Nahr

Why cannot I use the == operator directly for value-types (not primitive
types like int, float, double etc)? Why do I need to either have an implicit
operator (to type-cast to primitive type) or override/overlaod the ==
operator myself?

I'm assuming what you want is a default definition of operator== for
value types that does a bitwise comparison of all member variables.

I agree that would have been convenient since it's normally exactly
what you want. No idea why the .NET team didn't do that. They might
have judged it not worth the effort since user-defined value types are
(or should be) rare.
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

MasterGaurav said:
Hi,

I have a, probably very basic, query on value-types.

Why cannot I use the == operator directly for value-types (not primitive
types like int, float, double etc)? Why do I need to either have an implicit
operator (to type-cast to primitive type) or override/overlaod the ==
operator myself?

Because a binary comparison of structures doesn't always make sense.

Example:

public struct Name {

private string _first, _last;

public Name(string first, last) {
_first = first; _last = last;
}

public string First { get { return _first; } }
public string Last { get { return _last; } }
}

Name person1 = new Name("Peter", "Parker");
string er = "er";
Name person2 = new Name("Pet" + er, "Park" + er);

Now you have two structures with different binary values, but the same
logical values.
 
L

Laura T.

Different binary values? How's that? IMO, they (person1 and person2) are the
same, bit per bit.
The assignment will be made as strings with the same value, despite the
expression for person2.
 
L

Laura T.

The standard does not allow for automatic operator overloading, by default,
as they are not CLS compliant.
If your language supports operator overloading, good for you, but you must
implement it by yourself.

Sometimes you must make your own implementation. For example:

public struct NamedBuffer
{
public readonly string bufferName;
byte[] myByte;

public NamedBuffer(string BufName)
{
bufferName = BufName;
myByte = new byte[65535];
}
}

static void Main(string[] args)
{
NamedBuffer buf1 = new NamedBuffer("hello");
NamedBuffer buf2 = new NamedBuffer("hello");
bool theSame = buf1.Equals(buf2);
}


The buffers are not same, if you let the system to use it's bitwise
comparision.

And, sometimes it's good to roll on your own for performance reasons.
 
B

Ben Voigt

Laura T. said:
Different binary values?
That's right.
How's that? IMO, they (person1 and person2) are the same, bit per bit.
That's your opinion, not real life.
The assignment will be made as strings with the same value, despite the
expression for person2.
The content of the two string objects will be the same. But strings are a
reference type. Each of the two string objects will be stored at a
different address, and it's that address which is contained within the value
type.

However, the compiler could easily provide an automatic member-by-member
equality operator, rather than as a raw blob. That's up to the language
designer though (the CLR doesn't prevent it).
 
J

Jon Skeet [C# MVP]

Different binary values? How's that? IMO, they (person1 and person2) are the
same, bit per bit.
Nope.

The assignment will be made as strings with the same value, despite the
expression for person2.

Strings are reference types. person1 and person2 will have references
to different strings, therefore the bit-for-bit contents of person1
and person2 will differ. The two string objects will be *equal*, but
they will still be separate objects.

Jon
 
L

Laura T.

Well, if you put it in that way, that references have different memory
location, yes, that would be right.
But that does not make person1 and person2 to be different for CLR (try
person1.Equals(person2);).
The automatic value type comparator uses field by field comparision when it
can (via System.RuntimeType.GetFieldCandidates) rather than strict memcmp,
so after the day, person1==person2 => true.
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Laura said:
Well, if you put it in that way, that references have different memory
location, yes, that would be right.
But that does not make person1 and person2 to be different for CLR (try
person1.Equals(person2);).

That is because the Equals method is overridden in the String class to
compare the values of the strings instead of the references.
The automatic value type comparator uses field by field comparision when it
can (via System.RuntimeType.GetFieldCandidates) rather than strict memcmp,
so after the day, person1==person2 => true.

Yes, but that means that a default comparer would either have to use
reflection to compare the values (which isn't that effective), or it
would have to be created by the compiler.

If you would always have a default comparer, it means that you would be
forced to implement a comparer whenever the default comparer doesn't
make sense.

Also it implies that comparing values always makes sense. If it doesn't,
you would have to override the comparer and throw an exception if
someone tries to use it.
 
M

MasterGaurav \(www.edujini-labs.com\)

The standard does not allow for automatic operator overloading, by
default, as they are not CLS compliant.
If your language supports operator overloading, good for you, but you must
implement it by yourself.

Wondering why is has not been overloaded in System.ValueType.

IMHO, if the method Equals has been overridden, it makes sense to overload
the op_Equality operator as well.
Well, may not be in general, but at least for value-types since we are
anyway checking for value.


--
Happy Hacking,
Gaurav Vaish | www.mastergaurav.com
www.edujini-labs.com
http://eduzine.edujini-labs.com
-----------------------------------------
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

MasterGaurav said:
Wondering why is has not been overloaded in System.ValueType.

Because that would make it impossible to create a CLR compliant assembly.
IMHO, if the method Equals has been overridden, it makes sense to overload
the op_Equality operator as well.
Well, may not be in general, but at least for value-types since we are
anyway checking for value.

Yes, often so, but you don't always want to compare all the values in a
structure.

Take for example a structure that handles the setting of a light dimmer:

public struct LightDimmer {

private bool _on;
private int _intendity;

public LightDimmer(bool on, int intensity) {
_on = on;
_intensity = intensity;
}

public bool On { get { return _on; } }
public bool Off { get { return !_on; } }
public int Intensity { get { return _intensity; } }

public static bool operator == (LightDimmer d1, LightDimmer d2) {
if (d1.Off && d2.Off) return true;
if (d1.Off || d2.Off) return false;
return d1.Intensity == d2.Intensity;
}

}

The on/off state is separate from the intensity setting, as a dimmer
keeps the intensity setting even when turned off.

If you compare two settings, and both are turned off, you want them to
be equal eventhough the intensity would be different if both were turned
on. If you would compare all the values of the structures without this
logic, they would be different eventhough both rooms are currently
equally dark.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top