Есть ли способ в C # для принудительной перегрузки операторов в производных классах? - PullRequest
19 голосов
/ 28 сентября 2010

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

Ответы [ 6 ]

23 голосов
/ 28 сентября 2010

Немного взлома, но ...

Вы можете обеспечить перегрузки операторов в базовом классе, которые затем вызовут некоторые опубликованные абстрактные методы в одном из классов, чтобы выполнить работу там.

public abstract class MyClass
{
    public static MyClass operator +(MyClass c1, MyClass c2) 
    {
        return c1.__DoAddition(c2);
    }

    protected abstract MyClass __DoAddition(MyClass c2);
}
8 голосов
/ 28 сентября 2010

Нет.Единственный разумный способ сделать это - использовать проверку модульного теста с использованием отражения, чтобы найти все конкретные реализации, а затем проверить это условие.Вы могли бы также возможно сделать что-то во время выполнения повторно через статический конструктор, но тогда возникает вопрос , какой статический конструктор?

Другой подход состоит в отбрасывании операторови использовать интерфейсный подход;например, если вам нужно T, чтобы иметь +(T,T), тогда вместо операторов есть интерфейс с методом Add(T).Другое преимущество заключается в том, что интерфейсы можно использовать из обобщенных (обычно через ограничения), тогда как использование операторов из обобщенного кода требует определенных усилий.

5 голосов
/ 28 сентября 2010

Вы можете реализовать перегрузку в абстрактном базовом классе, но делегировать фактические особенности операции абстрактному методу. Тогда это должно быть реализовано, и перегрузка будет устранена при их реализации.

public abstract class OverLoadingBase
{
    public abstract OverLoadingBase DoAdd(OverLoadingBase y);

    public static OverLoadingBase operator +(OverLoadingBase x, OverLoadingBase y)
    {
        return x.DoAdd(y);
    }    
}

Хотя я не уверен, что это завершено.

4 голосов
/ 19 августа 2014

Я делал это в прошлом ...

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)
    {
        ...
    }
}
1 голос
/ 28 сентября 2010

Поскольку его оператор может быть только перегружен и не переопределен, это довольно сложно. Лучшее решение, которое я могу придумать, - это использовать абстрактный класс и перегрузку следующим образом.

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);
    }
}
0 голосов
/ 05 июня 2019

Я бы сделал что-то вроде:

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;
...