views:

191

answers:

3

I have a domain model that is trivially represented by the following.

IMyInterface

ClassA : IMyInterface

ClassB : IMyInterface

What I want is to implement IEquatable in such a way that I can write code something like.

if(dynamicallyCreatedInstanceOfClassA == dynamicallyCreatedinstanceOfClassB)
{
  // Do something relevant
}

My first inclination was to have IMyInterface implement IEquatable but of course I can't actually do the implementing in IMyInterface. I would have to do that in ClassA and ClassB. What strikes me as wrong with this solution is that the implementations of IEquatable in ClassA and ClassB will be exactly, line for line the same. Is there an elegant way to accomplish this? When ClassC comes along I don't want to have to copy and past 50 lines of duplicated IEquatable code.

I have considered using an abstract base class instead of an interface, but in this scenario IMyInterface really just describes actions the class will perform and not what the class is. ClassA and ClassB don't share many similarities except they can both perform the actions in the IMyInterface contract.

Any insights are helpful, and thank you for your time.

A: 

I would think that if the interface can't be converted to an abstract class, it doesn't make much sense to be comparing the two implemented classes to each other directly or automatically. Meaning that implementing a custom comparison on each class would be the way to go. I'm sure you can refactor the comparison code somehow to make changing it easier later on.

Jon Seigel
+2  A: 

Based on your question it seems like you know what the Equals algorithm will be and that it will be the exactly the same for both ClassA and ClassB. Why not do the following

  1. Define IMyInterface to inherit from IEquatable<IMyInterface>
  2. Define an abstract base class MyInterfaceBase which implements IMyInterface and has the IEquatable<IMyInterface> implementation
  3. Have ClassA and ClassB derive from MyInterfaceBase
JaredPar
I had considered this as well, I've been afraid that classA will need to inherit in the near future to achieve other goals, I can of course cross that bridge when I come to it, If I am going to go down this route I may as well just cut out the interface and use an abstract base class. Not out of the question either. Thanks for the input.
Matthew Vines
+3  A: 

Instead of implementing IEquatable<T>, could you perhaps implement IEqualityComparer<T> in a separate class? In most cases where you're interested in equality you can specify a comparer instead, and I suspect it'll be cleaner that way.

Jon Skeet
That's a good idea Jon, thanks for the input. I've just about read through C# in Depth, and it has taught me a ton about the language I hadn't even considered before. I'll be reading it a second time immediately just to try to soak it all up.
Matthew Vines
@Matthew: You might want to wait until the second edition is out for a second read - otherwise you'll need to read it all *three* times :)
Jon Skeet
That's a good point, what is the eta on the second edition?
Matthew Vines
You can get it on MEAP now (http://manning.com/skeet2) - the "new" chapters are basically done; I'm now revising the old ones. Should be out in hard copy some time H1 2010.
Jon Skeet
Awesome, I will have to check it out. And thanks again for the tip on IEqualityComparer<T> It worked out great.
Matthew Vines