singlepost

Перегрузка оператора в generic классе C# << На главную или назад  

Имеется, значит классTVector<T> – некое подобие вектора STL.
class TVector<T>
{
public T[] mas;
}

Требуется переопределить для сего класса оператор, ну скажем, +, чтобы к каждому элементу массива прибавлял число.
Что-то вроде:
public static TVector<T> operator +(TVector<T> vec, T a);
при таком раскладе компилятор ругается, что мол не может он сложить Т с Т, ибо фиг его знает, может там какой-нить нескладываемый тип.
Если записать что-то типа того:
public static TVector<int> operator +(TVector<int> vec,int a);
он еррорит, типа один из параметров должен быть типа TVector<T> и опять же не компилится.
подскажите, как мне быть, вероятно есть какой-нибудь способ преодолеть данную проблему, возможно что-то с помощью рефлексии, но я не соображу как(((

19 ответов в теме “Перегрузка оператора в generic классе C#”

  1. 18
    Доктор Хаус ответил:

    реализую чуть позже, сейчас нехватка времени. Выложу обязательно!

  2. 17
    Константин Дёмин ответил:

    Реализуете – выложите сюда. Очень жду :)

  3. 16
    Анатолий Медынцев ответил:

    Только мне кажется операторы в интерфейсе не определить. Так что скорее абстрактный класс

  4. 15
    Константин Дёмин ответил:

    Да, вспомнил. Где-то видел более-менее приличный обход этой проблемы через привязку типа-параметра T к некоторому интерфейсу, а потом создание нескольких пользовательских типов от родных System.Int64 и пр. рантаймовых типов в нагрузку к реализации этого интерфейса. В итоге, получались типы вроде MyNamespace.Int64, которые можно просто писать как Int64. Особенных неудобств вроде не создавало.

  5. 14
    Константин Дёмин ответил:

    Артём, не всё так просто, как кажется с начала. :)

    Анатолий, это вариант, но, имхо, компилятору пофиг – он не знает о типе-параметре T.

    Так, если кто-то не понимает, что надо сделать, пишу:
    надо заставить компилятор думать, что тип-параметр T в дженерике содержит объявления для операторов "+", "-" и т.п. Если всё ещё не понятно, откомпилируйте это:

    //некоторый некомпилирующийся в принципе дженерик
    class SomeBuggyGeneric<T> {
    //реализация метода не важна;
    //допустим, что он работает на все 100%
    void Add(T x);

    //а вот и гвоздь программы!
    void AddSum(T x, T y) {
    Add(x + y);//<=интересно, что Вам скажет компилятор? ;)
    }

    }

  6. 13
    Анатолий Медынцев ответил:

    А если для каждого типа отдельно перегрузить:
    public static TVector<T> operator +(TVector<T> vec, inta);
    public static TVector<T> operator +(TVector<T> vec, doublea);
    etc.

  7. 12
    Доктор Хаус ответил:

    Никто не говорит, что не нравится. Просто нужно перегрузить оператор.

  8. 11
    Константин Дёмин ответил:

    C# был спроектирован таким образом чуть ли не изначально. Хватит пороть горячку. Не нравится шарп – пишите на C++/CLR.

  9. 10
    Доктор Хаус ответил:

    Наследуется) НО в общем, все типы С# наследуются от Object, так что это ничего не даёт(

  10. 9
    Володя Фурсо ответил:

    А разве тот же intне наследуется следующим образом int<-ValuedType<-Object?

  11. 8
    Доктор Хаус ответил:

    Да, блин, С# еще дорабатывать надо и дорабатывать, версии к 6 сделают конфетку. Ладно, буду типы перечислять, да здравствует хардкод!

  12. 7
    Guess Who ответил:

    Кстати, на счет рефлексии…
    Пусть компилятор не знает, что у твоего класса есть статический метод operator+ (например, аргумент является типом Object). И, допустим, ты узнал, что класс переданной тебе переменной имеет статический член operator+. Что ты с ним будешь потом делать =)? Ведь чтобы сложить переданный класс, надо привести этот объект с своему же типу =), что в С# тоже не предусмотренно!

  13. 6
    Guess Who ответил:

    Ну есть такой прикол в C#: в нем численные типы не наследуются от какого-то базового (как в Ruby, например :) ). А поскольку в качестве соглашения в C# Generics пишется интерфейс (или какой-нибудь базовый класс), то иным способом кроме как перечислением типов не получится написать твой код, т.к. нет никакой возможности указать, что тип должен реализовать именно operator+ независимо от его "родословной".
    З.Ы. Ну да, тут реальный промах в дизайне C#.

  14. 5
    Доктор Хаус ответил:

    Александр, извините за мою необразованность, но я так понял, нужно создать интерфейс, и проверять через where, что-то типа того:

    interface ISum
    {
    //наличие оператора +
    }

    class TVector<Т>
    where T: ISum
    {
    //
    }

    Но мой компилятор ругается, мол нельзя операторы в интерфейс.

    либо, как я понял, хардкодить через where возможность, что Т – int, double, float…
    class TVector<T>
    where T : int, double, float, другой_тип_где_есть_+
    {
    }
    Но это как-то не универсально.
    Может быть есть возможность узнать точно, поддерживается ли типом отператор +? Напишите код, если не трудно, в нете искал, ничего путного не нашел, кроме проверки на интерфейс, что мне не подходит и хардкодного перечисления типов, которых может быть уйма…

  15. 4
    Доктор Хаус ответил:

    Александр Кульдин, спасибо огромное! Про where вообще первый раз слышу(

  16. 3
    Guess Who ответил:

    В первую очередь надо бы указать, что T является типом, в котором есть operator+ (используя слово 'where').

  17. 2
    Guess Who ответил:

    З.Ы. Это заметное отличие от C++, где ты можешь вызывать любые методы T, лишь бы при инстанцировании они были…

  18. 1
    Артём Шалхаков ответил:

    В C# есть классы типов?

    Есть ли там специализация шаблонов? (Это уж совсем крайний случай)

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.