I have an implementation of a specification template, and I wanted to change it to support contravariance. However, an interesting problem arose.
public interface ISpecification<in T> { Func<T, bool> Predicate { get; } bool IsSatisfiedBy(T entity); } public class Specification<T> : ISpecification<T> { public Specification(Func<T, bool> predicate) { this.Predicate = predicate; } public Func<T, bool> Predicate { get; private set; } public bool IsSatisfiedBy(T x) { return Predicate.Invoke(x); } public static Specification<T> operator &(Specification<T> left, ISpecification<T> right) { return new Specification<T>((x) => left.Predicate(x) && right.Predicate(x)); } }
this job as you can expect
new Specification<DerivedClass>((x) => true) & new Specification<BaseClass> ((x) => true)
but if I reverse the order of the argument, it no longer compiles
new Specification<BaseClass>((x) => true) & new Specification<DerivedClass>((x) => true)
I understand why this happens, but my question is: is there a way to work how?
EDIT:
I already tried to define the operator with the reverse order or parameters like
public static Specification<T> operator &(ISpecification<T> left, Specification<T> right) { return new Specification<T>((x) => left.Predicate(x) && right.Predicate(x)); }
but I get an ambiguous call compiler error between both statements. I am using .NET 4.5
netfiddle: https://dotnetfiddle.net/GB66UN
source share