I am trying to combine a couple of packages. UnitsNet containing all specific structs, and Microsoft Mvvm that hasa some nice Set<T> functions for properties with INotifyPropertyChanged. One of those Set<T> functions asks for an IEqualityComparer<T>.
I know that my QuantityEqualityComparer is the same for every struct from UnitsNet. And I saw that IEqualityComparer<in T> is contravariant. So I thought I understood that the following example should be possible. But the equality comparer is not accepted in this generic method.
It doesn't seem to be possible to cast _bar to IQuantity, and I also tried to call Set<IQuantity>(). But both statements get rejected by the compiler.
The solution I have implemented now is a caching mechanism that will create specific IEqualityComparers with reflection, but it seems like an overkill.
You can find the example here to play with it: https://dotnetfiddle.net/N7vfc9
using System;
using System.Collections.Generic;
public class Program
{
private static Length _bar;
public static void Main()
{
// Error: cannot convert from QuantityEqualityComparer to IEqualityComparer<Length>
Set(ref _bar, new Length(), new QuantityEqualityComparer());
}
// from Mvvm
public static bool Set<T>(ref T field, T value, IEqualityComparer<T> comparer)
{
return true;
}
}
public class QuantityEqualityComparer : IEqualityComparer<IQuantity>
{
public bool Equals(IQuantity x, IQuantity y)
{
// custom implementation
}
public int GetHashCode(IQuantity obj)
{
// custom implementation
}
}
// from UnitsNet
public interface IQuantity
{
}
public struct Length : IQuantity, IEquatable<Length>
{
public bool Equals(Length other)
{
return true;
}
}