Подтвердить что ты не робот

Есть ли способ в С# для принудительной перегрузки оператора в производных классах?

Мне нужно определить интерфейс, который должен обеспечить определенную перегрузку оператора для типов, которые ее реализуют. Нет очевидного способа сделать это, поскольку перегрузка оператора должна выполняться с использованием статических методов в классе. Есть ли способ достичь такого же эффекта (используя абстрактные классы или что-то еще)?

4b9b3361

Ответ 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;