views:

779

answers:

9

I wanna to compare two objects, for example:

 DirectoryInfo di1 = new DirectoryInfo("C:\\");
 DirectoryInfo di2 = new DirectoryInfo("C:\\");

OK, yeah I know we have here different reference, this class doesn't implement IComparable, and even GetHashCode is returning the different results.

But they are the same! (logically:))

I know that I can use reflection to compare every field and property between the classes, but it's too slow.

I can also use serialization; serialize every object and compare binary data, but that is even more slow!

Any other ideas??

+1  A: 

Write a function that does the comparison. For example, given this type:

class Foo
{
    public int Bar;
}

Write a function like this:

static Boolean areEqual(Foo first, Foo second)
{
    return first.Bar == second.Bar;
}

Edit

Here is how you would do this as an extension method:

static class Extensions
{
    public static Boolean Equals(this Foo source, Foo foo)
    {
        return first.Bar == second.Bar;
    }
}

Which would allow you to do this:

Foo first = new Foo();
Foo second = new Foo();
Boolean areEqual = first.Equals(second);
Andrew Hare
Bonus points if you do it as an extension method.
Joel Coehoorn
Nice call - I edited my answer to include that.
Andrew Hare
A: 

This is the raison d'etre of the IEquatable interface, which is a strongly-typed version of the old-as-the-hills object.Equals() method. (or perhaps IComparable, but you mentioned it doesn't implement it.)

If you were deriving your own object with a sensible meaning of "equality" that doesn't mean "the same reference", then you should implement IEquatable and/or override object.Equals(). Given that you're using an object with none of this, you'll have to create a function to compare their relevant properties in whatever way you see fit.

mquander
problem is, this is DirectoryInfo, and it's sealed (a whole other bad design diatribe-worthy subject)
Michael Meadows
Thus my last sentence -- he'll just have to do it himself.
mquander
Agreed, just thought I would add my frustration with sealed classes. Assert.That(SealedClasses.Are(Stupid));
Michael Meadows
A: 

Is it the DirectoryInfo paths you want to compare? Use .ToString() and compare the paths in string format.

Björn
+3  A: 

What's wrong with di1.FullPath == di2.FullPath?

If the full paths are the same, you can derive that they are the same directory, even if the instance properties differ. A deeper comparison would seem pointless in most cases.

Michael Meadows
DirectoryInfo has more properties than just Fullpath
Henk Holterman
True, but if the full paths are the same, you can derive that they are the same directory, even if the instance properties differ. A deeper comparison would seem pointless in most cases.
Michael Meadows
+1  A: 

Yes, ideally GetHashCode() should return the same value for the same data, but there are a lot of classes in the .NET framework that rely on the default behavior of having different values for different references.

That being said, GetHashCode() returning the same value should NOT be used as an indicator of equality on any class. This function is designed to assist in in-memory storage of hashtable (and similar) structures, where there is use for an approximate equality or close value function.

In your case, your only real option is to write your own. If this is for use in something like an IDictionary, then you'll need to just create a concrete class that implements the IEqualityComparer interface.

In short, there is no general, one-size-fits-all method of determining data equality on a reference type, as the meaning can (and will) change for various types.

Adam Robinson
A: 

I think reflection is about the only thing that will work. You could optimize it using code gen or even using LINQ expressions.

wekempf
+5  A: 

I would recommend creating an implementation of IEqualityComparer<DirectoryInfo> and encapsulate the equality checking code in there. Here is the link for the documentation on IEqualityComparer<T>:

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

casperOne
A: 

What do you actually want to compare?

  1. The paths
  2. The number of files in each directory, and their paths
  3. All child file paths
  4. All child files, and all their attributes (that is a lot of comparisons)
  5. All child directories
  6. All child files, and all their attributes (ditto to 3)
  7. All of the above

Once you've figured that out you can go about writing your comparison in hashcode or IComparable, IComparer, Equals, Equatable and so on.

A windows path is what I'd personally check, using a hashcode of the string. You can't have "C:\blah" and "C:\Blah", however you can in Unix based operating systems (or C:\ would be / or ~/).

So checking the two paths is in my view, fine. Just as Michael Meadows write.

Chris S
A: 

I have created a class to perform a deep compare of .NET Objects. See:

http://comparenetobjects.codeplex.com/

Greg Finzer