2

I have created a Graph Class including HashSet<T> as Nodes and HashSet<IEdge<T>> as Edges.

public interface IEdge<T>
{
    T A_Node { get; }
    T Another_Node { get; }
}


public interface IGraph<T>
{
    ISet<T> Nodes { get; }
    ISet<IEdge<T>> Edges { get; }
}

I want to avoid adding duplicate Nodes and Edges to my Graph.

Based on this Question :

1) IEqualityComparer is an interface for an object that performs the comparison on two objects of the type T.

2) IEquatable is for an object of type T so that it can compare itself to another.

also

3) If there is only one way of testing two instances of T for equality, or if one of several methods is preferred One instance of T has internal knowledge of how to compare itself to another instance of T.

4) On the other hand, if there are several equally reasonable methods of comparing two Ts for equality, IEqualityComparer would seem more appropriate

5) This interface is not meant to be implemented by T itself, but by other "external" classes.

Based on these tips(1-5) and my code, I need to have IEdge be able to compare itself to another.

Also there is only one way of testing two instances of T or IEdge for equality.

So It seems Implementing IEquatable is the solution.

But the problem is that HashSets use GetHashCode method.

And IEquatable doesn't force to override GetHashCode method.

How can I use IEquatable and in the same time force the developer to override GetHashCode ?!

If you prefer using IEqualityComparer<T> or EqualityComparer<T> in this case, doesn't it matter that it has conflict with Tips above ?

Parsa
  • 7,995
  • 2
  • 27
  • 37
  • 1
    You could encapsulate the collection of edges and in a provided `Add()` method, perform the duplication checks you want. It would be up to the concrete `Graph` type then to deal with that, which seems like it makes sense anyway. – itsme86 Oct 14 '19 at 14:47
  • But I think if the T or IEdge has an overrided GetHashCode method , the HashSet works better. And I'm searching for a way to force developer to override GetHashCode too by using Interfaces. There is EqualityComparer but I think it's concept does not match.Is using EqualityComparer wrong or it's ok !? – Parsa Oct 14 '19 at 14:58
  • 2
    No, `IEqualityComparer` is for something else comparing edges. Like if you wanted to allow someone to specify a custom equality check for my proposed `Add()` method, you could have an `IEqualityComparer comparer` parameter. Then the `Add()` method would do something like `comparer.Equals(edge1, edge2)`. – itsme86 Oct 14 '19 at 15:04
  • 1
    Are you talking about having `IEdge` implement `IEqualityComparer>`? Because even if you do that, `HashSet` won't use the `IEqualityComparer.GetHashCode(T)` implementation by default. If you don't provide an `IEqualityComparer` to `HashSet` then it just uses the default one which uses `object.GetHashCode` and either `IEquatable.Equals(T)` or `object.Equals(object)`. – Joshua Robinson Oct 14 '19 at 15:07
  • 2
    Yeah, I reckon you'll be wanting to implement your own `IEqualityComparer` to use with the HashSet, and pass it to the appropriate HashSet constructor. – Matthew Watson Oct 14 '19 at 15:15
  • 3
    Types that implement `IEquatable` should already override `GetHashCode` (and `Equals(object)`) - see the [remarks in the documentation](https://learn.microsoft.com/en-us/dotnet/api/system.iequatable-1?view=netframework-4.8#notes-to-implementers). – Lee Oct 14 '19 at 15:23
  • @Lee I find it weird based on the links you sent that when we implement IEquatable we should also override GetHashCode method BUT this isn't forced in IEquatable interface ! I think finally I should remind and ask the one who use my library to override GetHashCode too ! Kinda Odd ! – Parsa Oct 14 '19 at 15:35
  • 2
    Interfaces can't require implementers to override other virtual methods and since `GetHashCode` is defined in `object` there isn't a way to enforce it in the type system. Ideally `Equals(object)` and `GetHashCode` wouldn't be defined on `object` at all. – Lee Oct 14 '19 at 16:06
  • 1
    As @Lee has explained, an interface simply states what members a type must implement. Since all types in .NET already implement `Equals(object)` and `GetHashCode()`, all objects trivially would satisfy any such requirement in an interface. If you want to enforce implementation, you need to use an `abstract` class instead (which in a very real sense is just an interface that optionally has some implementation already defined). See marked duplicate. – Peter Duniho Oct 14 '19 at 16:24

0 Answers0