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 IEqualityComparer
s 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;
}
}