Вы не можете определить приведение или перегрузку оператора на интерфейсах. Поскольку интерфейс - это контракт, описывающий членов, которые всегда будут доступны (либо как явное приведение к этому интерфейсу, либо как открытые члены), и ничего более нельзя полагаться на интерфейсы, содержащие какую-либо встроенную логику, например, как приведение типов. или как операторы будут работать с этим интерфейсом.
Вы все еще можете наследовать от абстрактного базового класса, который реализует интерфейс и предоставляет логику, необходимую для приведений или перегрузки операторов. Это не нарушает дизайн интерфейса. Классы, которые не наследуют от общего базового класса, но реализуют интерфейс, все равно должны будут независимо реализовывать свои собственные неявные приведения и перегрузки операторов. Если вы хотите централизовать логику для работы с классами, которые обычно реализуют интерфейс, вы можете сделать это в C # 3.0 + /. NET Fx 3.5 с методами расширения (или в предыдущих версиях со статическими методами). Ниже я продемонстрирую это с помощью служебного класса и двух классов, Foo и Bar, которые не имеют общего предка. Они разделяют код, который включает в себя служебную функцию Add, поэтому вам не нужно повторять эту реализацию в обоих классах.
public interface IInterface
{
int X { get; set; }
int Y { get; set; }
}
public static class IInterfaceTHelper
{
public static IInterface Add<T>(this IInterface a, IInterface b)
where T : new()
{
var ret = (IInterface)new T();
ret.X = a.X + b.X;
ret.Y = a.Y + b.Y;
return ret;
}
}
class Foo : IInterface
{
public int X { get; set; }
public int Y { get; set; }
public static IInterface operator +(Foo a, IInterface b)
{
return a.Add<Foo>(b);
}
}
class Bar : IInterface
{
public int X { get; set; }
public int Y { get; set; }
public static IInterface operator +(Bar a, IInterface b)
{
return a.Add<Bar>(b);
}
}
class Program
{
static void Main(string[] args)
{
var foo = new Foo { X = 5, Y = 3 };
var bar = new Bar { X = 3, Y = 5 };
var result = foo + bar;
Console.WriteLine(result.GetType().Name + " " + result.X + " " + result.Y);
result = bar + foo;
Console.WriteLine(result.GetType().Name + " " + result.X + " " + result.Y);
Console.ReadLine();
}
}
Если ваши интерфейсы содержат больше, чем просто контракты, которые нарушают дизайн по контракту.