Имеется, значит класс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> и опять же не компилится.
подскажите, как мне быть, вероятно есть какой-нибудь способ преодолеть данную проблему, возможно что-то с помощью рефлексии, но я не соображу как(((
11 ноября 2008 в 16:04
реализую чуть позже, сейчас нехватка времени. Выложу обязательно!
7 ноября 2008 в 23:00
Реализуете – выложите сюда. Очень жду
6 ноября 2008 в 19:03
Только мне кажется операторы в интерфейсе не определить. Так что скорее абстрактный класс
6 ноября 2008 в 14:00
Да, вспомнил. Где-то видел более-менее приличный обход этой проблемы через привязку типа-параметра T к некоторому интерфейсу, а потом создание нескольких пользовательских типов от родных System.Int64 и пр. рантаймовых типов в нагрузку к реализации этого интерфейса. В итоге, получались типы вроде MyNamespace.Int64, которые можно просто писать как Int64. Особенных неудобств вроде не создавало.
6 ноября 2008 в 13:05
Артём, не всё так просто, как кажется с начала.
Анатолий, это вариант, но, имхо, компилятору пофиг – он не знает о типе-параметре T.
Так, если кто-то не понимает, что надо сделать, пишу:
надо заставить компилятор думать, что тип-параметр T в дженерике содержит объявления для операторов "+", "-" и т.п. Если всё ещё не понятно, откомпилируйте это:
//некоторый некомпилирующийся в принципе дженерик
class SomeBuggyGeneric<T> {
//реализация метода не важна;
//допустим, что он работает на все 100%
void Add(T x);
//а вот и гвоздь программы!
void AddSum(T x, T y) {
Add(x + y);//<=интересно, что Вам скажет компилятор?
}
}
6 ноября 2008 в 11:03
А если для каждого типа отдельно перегрузить:
public static TVector<T> operator +(TVector<T> vec, inta);
public static TVector<T> operator +(TVector<T> vec, doublea);
etc.
6 ноября 2008 в 7:04
Никто не говорит, что не нравится. Просто нужно перегрузить оператор.
6 ноября 2008 в 4:03
C# был спроектирован таким образом чуть ли не изначально. Хватит пороть горячку. Не нравится шарп – пишите на C++/CLR.
5 ноября 2008 в 9:04
Наследуется) НО в общем, все типы С# наследуются от Object, так что это ничего не даёт(
4 ноября 2008 в 21:05
А разве тот же intне наследуется следующим образом int<-ValuedType<-Object?
4 ноября 2008 в 16:04
Да, блин, С# еще дорабатывать надо и дорабатывать, версии к 6 сделают конфетку. Ладно, буду типы перечислять, да здравствует хардкод!
4 ноября 2008 в 15:00
Кстати, на счет рефлексии…
Пусть компилятор не знает, что у твоего класса есть статический метод operator+ (например, аргумент является типом Object). И, допустим, ты узнал, что класс переданной тебе переменной имеет статический член operator+. Что ты с ним будешь потом делать =)? Ведь чтобы сложить переданный класс, надо привести этот объект с своему же типу =), что в С# тоже не предусмотренно!
4 ноября 2008 в 14:03
Ну есть такой прикол в C#: в нем численные типы не наследуются от какого-то базового (как в Ruby, например ). А поскольку в качестве соглашения в C# Generics пишется интерфейс (или какой-нибудь базовый класс), то иным способом кроме как перечислением типов не получится написать твой код, т.к. нет никакой возможности указать, что тип должен реализовать именно operator+ независимо от его "родословной".
З.Ы. Ну да, тут реальный промах в дизайне C#.
4 ноября 2008 в 12:02
Александр, извините за мою необразованность, но я так понял, нужно создать интерфейс, и проверять через where, что-то типа того:
interface ISum
{
//наличие оператора +
}
class TVector<Т>
where T: ISum
{
//
}
Но мой компилятор ругается, мол нельзя операторы в интерфейс.
либо, как я понял, хардкодить через where возможность, что Т – int, double, float…
class TVector<T>
where T : int, double, float, другой_тип_где_есть_+
{
}
Но это как-то не универсально.
Может быть есть возможность узнать точно, поддерживается ли типом отператор +? Напишите код, если не трудно, в нете искал, ничего путного не нашел, кроме проверки на интерфейс, что мне не подходит и хардкодного перечисления типов, которых может быть уйма…
4 ноября 2008 в 11:05
Александр Кульдин, спасибо огромное! Про where вообще первый раз слышу(
4 ноября 2008 в 10:05
В первую очередь надо бы указать, что T является типом, в котором есть operator+ (используя слово 'where').
4 ноября 2008 в 10:05
З.Ы. Это заметное отличие от C++, где ты можешь вызывать любые методы T, лишь бы при инстанцировании они были…
4 ноября 2008 в 7:00
В C# есть классы типов?
Есть ли там специализация шаблонов? (Это уж совсем крайний случай)