compare two structs via ==

  • Thread starter Thread starter titan nyquist
  • Start date Start date
T

titan nyquist

I wish to compare two structs via == but it does not compile. I can
overload and create my own == but am I missing something that c#
already has implemented?

~titan
 
No, you have not. If you overload ==, then you have to overload != as
well.

On top of that, you should also overload Equals and GetHashCode as well
to produce consistent results.
 
titan said:
I wish to compare two structs via == but it does not compile. I can
overload and create my own == but am I missing something that c#
already has implemented?

There is no default comparer for structs, as comparing the values as a
binary block of data doesn't always make sense.

If you for example have a struct:

public struct MyStruct {
private string _name;
public MyStruct(string name) { _name = name; }
public string Name { get { return _name; } }
}

If you then create two struct values that contains the same string value:

MyStruct v1 = new MyStruct("1");
MyStruct v2 = new MyStruct(1.ToString());

If you could compare these struct values as binary chunks of data, they
would not be equal, as the structs contains two different references,
eventhough the references points to string values that are equal.
 
There is no default comparer for structs, as comparing the values as a
binary block of data doesn't always make sense.

But why I can do this?

Point p1 = new Point(1, 2);

Point p2 = new Point(1, 2);

Console.WriteLine(p1 == p2);
 
There is no *default* equality operator. Point declares one itself -
look in "reflector" to see it.

Marc
 
Fabio said:
But why I can do this?

Point p1 = new Point(1, 2);

Point p2 = new Point(1, 2);

Console.WriteLine(p1 == p2);
Because an eqaulity operator is defined for Point in Point itself.

Christof
 
But why I can do this?

Point p1 = new Point(1, 2);
Point p2 = new Point(1, 2);
Console.WriteLine(p1 == p2);

Because Point overloads the equality operator itself, along with
addition, subtraction etc.

Jon
 
<snip>

Oops. Looks like the automatic reply generator for myself, Marc and
Christof has got out of sync... Time to reboot ourselves again, guys.

(Anticipating some sort of equivalent reply from Marc and Christof
now...)

Jon
 
<snip>

Oops. Looks like the automatic reply generator for myself, Marc and
Christof has got out of sync... Time to reboot ourselves again, guys.

(Anticipating some sort of equivalent reply from Marc and Christof
now...)

Jon

Hi,

This proves what the *asynchronous* fellows mentioned =)

[Serializable, StructLayout(LayoutKind.Sequential),
TypeConverter(typeof(PointConverter)), ComVisible(true)]
public struct Point
{
...
public static bool operator ==(Point left, Point right);
public static bool operator !=(Point left, Point right);
...
}

Moty
 
It'd be nice if C# generated a default memberwise equality operator, but I
suppose there's a good reason why it doesn't.

///ark
 
Mark said:
It'd be nice if C# generated a default memberwise equality operator, but I
suppose there's a good reason why it doesn't.

Yes, there is.

Did you miss my post explaining that a memberwise comparision dosen't
always make sense?
 
Did you miss my post explaining that a memberwise comparision dosen't
always make sense?

I saw the post from you talking about a bitwise comparison, but not a
memberwise comparison. In the latter, you'd compare each member, using its
== operator.

Did I miss a post?

///ark
 
Mark said:
I saw the post from you talking about a bitwise comparison, but not a
memberwise comparison. In the latter, you'd compare each member, using its
== operator.

Did I miss a post?

///ark

Ok, I misunderstood your distinction there. Anyway, not even a
memberwise comparison would always make sense.
 
Memberwise comparison worked pretty well in C++. An object is equal to
another object if all its members are equal to the other object's members
(using the same criterion for member equality).
 
Mark said:
Memberwise comparison worked pretty well in C++. An object is equal to
another object if all its members are equal to the other object's members
(using the same criterion for member equality).

Usually, but not always.

I have a faint memory of reading somewhere that the decision to not
include an automatic memberwise comparison for structs was that it would
automatically add functionality to all structs that you create. If the
comparison doesn't make sense for a struct, you would be forced to
override it even if it didn't make sense to compare the structs at all.
It would not be possible to prevent usage of the comparison at compile
time, it could only throw an exception at run time.

If you want a memberwise comparison for a struct, it's very easy to
write one, and you can most likely make it more efficient than any
automatically generated code, as you can choose the order to compare the
fields so that you first compare the fields that is most likely to differ.
 
If you want a memberwise comparison for a struct, it's very easy to
write one, and you can most likely make it more efficient than any
automatically generated code, as you can choose the order to compare the
fields so that you first compare the fields that is most likely to differ.

It's also worth bearing in mind that although the equality operators
aren't generated for you, ValueType.Equals does a memberwise
comparison, using a fast bit comparison where appropriate and calling
Equals on each field otherwise. It's not fast, but it works.

In other words, if you don't care about performance then implementing
== and != can be as simple as calling Equals.

(While I'm on the topic of == and !=, can anyone think of any reason
why you'd ever implement them to return a type other than bool? I
wasn't even aware it could be done until a few days ago.)

Jon
 
Oh dear... any readers of The Daily WTF (as was) will know that this
is so that you can return...

public enum TriBool {True, False, FileNotFound}

;-p
 
More sensibly... news to me too; I've just tested it, and you are
absolutely correct (which I fully expected, but sometimes you just
have to see these things for yourself).

Perhaps it realtes to lifted operators and null propegation for
Nullable<T> (334: 8.19)??

Marc
 
Ignore the lifted operator comment - reading more closely, comparison
operators are lifted in the arguments only (not the result).

There is also the unary true / false operator... but I'm still none
the wiser. Interesting.

Marc
 
More sensibly... news to me too; I've just tested it, and you are
absolutely correct (which I fully expected, but sometimes you just
have to see these things for yourself).

Perhaps it realtes to lifted operators and null propegation for
Nullable<T> (334: 8.19)??

Nope - because the lifted operators for equality *only* work when the
return type is bool, and the lifted form is still bool.

And yes, I know this from memory because I've just been writing about
it - it's
the only way I found out about the oddity to start with :)

Jon
 
Back
Top