Geeks With Blogs
Freestyle Coding Programming in the Real World

This had me pulling my hair out for a couple days:

byte[] _A = new byte[64];
// Fill _A with some meaningful, valid data.

byte[] _B = new byte[_A.Length];
_A.CopyTo( _B, 0 );

if( !_A.Equals( _B ) ) {
throw new WtfException(
"It appears object.Equals doesn't work on arrays of value types..."
);
}

Yes, that throws the WtfException. It took me a few days to notice. byte is a ValueType. However, byte[] is a System.Array, which is a reference type. As per the .NET documenation:

The default implementation of Equals supports reference equality for reference types, and bitwise equality for value types. Reference equality means the object references that are compared refer to the same object. Bitwise equality means the objects that are compared have the same binary representation.

_A and _B are not references to the same array. Thus, they are not equal. You need to make something like this:

private static bool ValueTypeArraysAreEqual( Array p_lhs, Array p_rhs ) {
if( p_lhs == null ) {
return p_rhs == null;
}

if( p_rhs == null ) {
return false;
}

if( p_lhs.Length != p_rhs.Length ) {
return false;
}

return Parallel.For( 0, p_lhs.Length, ( _lcv, loopState ) => {
if( !p_lhs.GetValue( _lcv ).Equals( p_rhs.GetValue( _lcv ) ) ) {
loopState.Break();
}
} ).IsCompleted;
}

I use object.Equal in the loops because I'm compairing the ValueTypes that the Loop contains. The use of System.Threading.Tasks.Parallel helps me move things along a little quicker. Parallel.For returns an struct that tells you whether the loop was halted. If I never halted the loop with loopState.Break, then they all matched. If, for some reason, you can't use Parallel.For, just do a for loop that returns false;

Posted on Thursday, September 15, 2011 1:51 PM .NET , C# | Back to top


Comments on this post: Arrays of ValueTypes don't like object.Equals

# re: Arrays of ValueTypes don't like object.Equals
Requesting Gravatar...
You could use SequenceEqual.

http://msdn.microsoft.com/en-us/library/bb348567.aspx

_A.SequenceEqual(_B) == true
Left by Ryan on Sep 15, 2011 6:33 PM

# re: Arrays of ValueTypes don't like object.Equals
Requesting Gravatar...
I will admit that there is more than one way to do it. The primary point was to mention that .NET did not overload equals for System.Array, which was what I had assumed. I also used the opportunity to draw attention to the Parallel Extension Library, especially the fact that you can use the ParallelLoopState version to bail out early. It's something I don't get to use a lot in XNA, due to the fact that the Parallel Extension Library isn't supported in the .NET Compact Framework.

I tend to not use (or even think about) Linq for 2 reasons. First and most obvious, Linq is not supported in XNA. However, the other reason is that the first version of Linq (from .NET 3.5) was REALLY inefficient compared to single purpose code. The .NET 4 version and the PLinq extension are much better, but I habit on not using it was already set.

In an experiment, I ran 10,000 iterations of comparing two byte[1024]. The differences between the custom Parallel Extension and the PLinq version was about between 150 and 200 milliseconds. That's under 20 microseconds per iteration. At that point, you could basically use which ever you wished.
Left by Chris Gardner on Sep 16, 2011 10:23 AM

Your comment:
 (will show your gravatar)


Copyright © Chris Gardner | Powered by: GeeksWithBlogs.net