Мне нужно определить интерфейс, который должен обеспечить определенную перегрузку оператора для типов, которые ее реализуют. Нет очевидного способа сделать это, поскольку перегрузка оператора должна выполняться с использованием статических методов в классе. Есть ли способ достичь такого же эффекта (используя абстрактные классы или что-то еще)?
Есть ли способ в С# для принудительной перегрузки оператора в производных классах?
Ответ 1
Немного взлома, но...
Вы можете предоставить перегрузку оператора в базовом классе, а затем вызвать некоторые опубликованные абстрактные методы в одном из классов, чтобы выполнить там работу.
public abstract class MyClass
{
public static MyClass operator +(MyClass c1, MyClass c2)
{
return c1.__DoAddition(c2);
}
protected abstract MyClass __DoAddition(MyClass c2);
}
Ответ 2
Нет. Единственным разумным способом сделать это было бы иметь отражение использования unit test для поиска всех конкретных реализаций, а затем проверить это условие. Возможно, вы также можете что-то сделать во время выполнения с помощью статического конструктора, но тогда возникает вопрос, какой статический конструктор?
Другой подход - отказаться от операторов и использовать интерфейсный подход; например, если вам нужно T
иметь +(T,T)
, то вместо операторов есть интерфейс с методом Add(T)
. Другим преимуществом здесь является то, что интерфейсы можно использовать из generics (обычно через ограничения), где - как использование операторов из общего кода требует определенных усилий.
Ответ 3
Вы можете реализовать перегрузку в абстрактном базовом классе, но делегировать специфику конкретной операции абстрактному методу. Затем это должно быть реализовано, и перегрузка не будет реализована.
public abstract class OverLoadingBase
{
public abstract OverLoadingBase DoAdd(OverLoadingBase y);
public static OverLoadingBase operator +(OverLoadingBase x, OverLoadingBase y)
{
return x.DoAdd(y);
}
}
Хотя я не уверен, что это завершено.
Ответ 4
Я сделал это в прошлом...
public abstract class BaseClass<TClass> where TClass : BaseClass
{
public static TClass operator +(TClass c1, TClass c2)
{
return c1.DoAddition(c2);
}
protected abstract TClass DoAddition(TClass c2);
}
И затем выполняется следующим образом:
public class ConcreteClass : BaseClass<ConcreteClass>
{
protected ConcreteClass DoAddition(ConcreteClass c2)
{
...
}
}
Ответ 5
Так как его оператор может быть только перегружен, а не переопределен, его довольно сложно. Лучшее решение, о котором я могу думать, - использовать абстрактный класс и перегружать, как это.
public abstract class MyBase
{
public abstract MyBase Add(MyBase right);
public abstract MyBase Subtract(MyBase right);
public static MyBase operator +(MyBase x, MyBase y)
{
//validation here
return x.Add(y);
}
public static MyBase operator -(MyBase x, MyBase y)
{
//validation here
return x.Subtract(y);
}
}
Ответ 6
Я бы сделал что-то вроде:
public abstract class Scalar<This> where This : Scalar<This>
{
public static This operator +(Scalar<This> a, This b) => a.Add(b);
public abstract This Add(This another);
...
}
Тогда вы можете наследовать скаляр как:
public sealed class Rational : Scalar<Rational>
{
public override Rational Add(Rational another)
{
...
}
...
}
И что это:
Rational a = ...;
Rational b = ...;
Rational sum = a + b;