An extremely important part of using structs is overriding the Equals and GetHashCode methods. If you don’t, you will get the default versions, which are not at all good for performance. To get an idea of how bad it is, use an IL viewer and look at the code for the ValueType.Equals method. It involves reflection over all the fields in the struct. There is, however, an optimization for blittable types. A blittable type is one that has the same in-memory representation in managed and unmanaged code. They are limited to the primitive numeric types (such as Int32, UInt64, for example, but not Decimal, which is not a primitive) and IntPtr/UIntPtr. If a struct is comprised of all blittable types, then the Equals implementation can do the equivalent of byte-for-byte memory compare across the whole struct. Just avoid this uncertainty and implement your own Equals method.
If you just override Equals(object other), then you are still going to have worse performance than necessary, because that method involves casting and boxing on value types. Instead, implement Equals(T other), where T is the type of your struct. This is what the IEquatable<T> interface is for, and all structs should implement it. During compilation, the compiler will prefer the more strongly typed version whenever possible. The following code snippet shows you an example.
struct Vector : IEquatable &lt;Vector&gt;; { public int X { get; set; } public int Y { get; set; } public int Z { get; set; } public int Magnitude { get; set; } public override bool Equals(object obj) { if (obj == null) { return false; } if (obj.GetType() != this.GetType()) { return false; } return this.Equals((Vector)obj); } public bool Equals(Vector other) { return this.X == other.X &amp;amp;amp;&amp;amp;amp; this.Y == other.Y &amp;amp;amp;&amp;amp;amp; this.Z == other.Z &amp;amp;amp;&amp;amp;amp; this.Magnitude == other.Magnitude; } public override int GetHashCode() { return X ^ Y ^ Z ^ Magnitude; } }
If a type implements IEquatable<T> .NET’s generic collections will detect its presence and use it to perform more efficient searches and sorts.
You may also want to implement the == and != operators on your value types and have them call the existing Equals(T) method.
Even if you never compare structs or put them in collections, I still encourage you to implement these methods. You will not always know how they will be used in the future and the price of the methods is only a few minutes of your time and a few bytes of IL that will never even get JITted.
It is not as important to override Equals and GetHashCode on classes because by default they only calculate equality based on their object reference. As long as that is a reasonable assumption for your objects, you can leave them as the default implementation.
For all your application development needs, visit www.verbat.com for a fiscally conscious proposal that meets your needs ( So I can keep this blog going as well!!!!)
Alternatively click through the link if you found this article interesting. (This will help the companies Search engine rankings)
Leave a Reply