none
Реализация шаблонов с возможностью выполнения арифметических операций RRS feed

  • Вопрос

  •  

    Около года назад читая разнообразную литературу по программированию на языках семейства C(C++, C#), встретился в книге по языку C++ с таким понятием, как "шаблон" - хорошая штука, которая может на-порядок уменьшить количество кода в приложении. Реализовал на языке C++ в среде C++Builder шаблон "комплексные числа"(реализовал операторы сложения, умножения, вычитания, деления и т.д. для созданного шаблона) - все отлично работало. Решил попробовать тоже самое реализовать на C# - добавил поля "действительная часть"(Re), "мнимая часть"(Im) типа T. Затем попробовал реализовать арифметические операции для созданного шаблона, но в ответ получил ошибку компилятора(что-то вроде "Оператор + не определен для типа T") и от данной затее пришлось отказаться. В данный момент появилось немного времени и я решил ради "спортивного интереса" разобраться в причине возникшей ошибки и как с ней можно было справиться.

    Просмотрел некоторые статьи MSDN, на одной из которых(http://msdn.microsoft.com/en-us/library/ms379564%28VS.80%29.aspx) нашел следующий код:

     

    public abstract class BaseCalculator<T>
    {
     public abstract T Add(T arg1,T arg2);
     public abstract T Subtract(T arg1,T arg2);
     public abstract T Divide(T arg1,T arg2);
     public abstract T Multiply(T arg1,T arg2);
    }
    public class MyCalculator : BaseCalculator<int>
    {
     public override int Add(int arg1, int arg2)
     {
     return arg1 + arg2;
     }
    
    } 
    

     


    Немного похоже на то, что требуется мне, но не более того(класс MyCalculator создается с уже конкретной "спецификацией типа").

    Попробовал сам сперва написать следующий код:

     

     class T 
    {
      public static extern T operator + (T val);
    public static extern T operator -(T val);
    }

     class Complex<T>
    {
    public
    T Re, Im;
    public
    Complex(T aRe, T aIm)
    {
    this
    .Re = aRe;
     this.Im = aIm;
    }

     public static Complex<T> operator +(Complex<T> value)
    {
    return new Complex<T>(this.Re + value.Re, this.Im + value.Im);
    }
     }

     

    Но во время компиляции получаю ошибку: 'Ключевое слово "this" не может использоваться в инициализаторах статических свойств, методов или полей'. Ладно, пробую модифицировать:

      class T
    {
    public static extern T operator + (T val1, T val2);
     public static extern T operator -(T val, T val2);
    }

    class Complex<T>
    {
    public T Re, Im;
     public Complex(T aRe, T aIm)
     {
    this.Re = aRe;
     this.Im = aIm;
     }
    public static Complex<T> operator +(Complex<T> value1, Complex<T> value2)
     {
     return new Complex<T>(value1.Re + value2.Re, value1.Im + value2.Im);
    }
    }
    Но при компиляции снова ошибка: 'Оператор "+" не может применяться к операндам типа "T" и "T" ' и предупреждение: 'Метод, оператор или метод доступа "ConsoleApplication2.T.operator +(ConsoleApplication2.T)" помечен как внешний и не имеет атрибутов. Для указания на внешнюю реализацию, возможно, следует добавить атрибут DllImport.'

    Ни черта понять не могу! Подскажите пожалуйста, каким же все таки образом возможно реализовать данный класс и перегрузить требуемые операторы? Возможно ли это вообще сделать на языке C# или это "дохлый номер"?



    17 августа 2011 г. 4:58

Ответы

  • Нельзя, точно, совсем никак.

    Могу обнадежить - в исходниках 4-го дотнета есть намеки на будущую поддержку операций для генериков, в виде закомментированных кусков типа:

      public struct Double : IComparable, IFormattable, IConvertible 
        , IComparable<Double>, IEquatable<Double>
    ///   , IArithmetic<Double> 
    
    


    и закомментированных реализаций интерфейса для стандартных типов. В исходниках 3.5.1 этих кусков кода не было.

    Но раньше 5-го C# поддержки со стороны компилятора точно не будет.

     

     


    My blog | My Favorite Project
    • Помечено в качестве ответа Maximys33 20 августа 2011 г. 8:26
    17 августа 2011 г. 11:53
    Модератор
    1. Выкачал MiscUtil-r285.dll;
    2. Переименовал выкачанный файл в MiscUtil.dll (Убрал из названия -r285);
    3. Создал новое консольное приложение;
    4. Подключил ссылку на переименованный файл;
    5. Добавил в проект класс, скопировал туда код преложенный Скитом.

    Все работает, исключений нет.

        static void Main(string[] args)
        {
          Complex<Double> tmp1 = new Complex<Double>(1, 2);
          Complex<Double> tmp2 = new Complex<Double>(3, 4);
          Complex<Double> tmp3 = tmp1 + tmp2; //строка 5
          Console.WriteLine("Значение после сложения: {0}", tmp3);
          Console.ReadLine();
        }
    


     

    • Помечено в качестве ответа Abolmasov Dmitry 6 сентября 2011 г. 16:35
    17 августа 2011 г. 13:12
    Модератор

Все ответы

  • Вот пример Скита реализации Complex'ного числа.
    А в твоем случае, по-моему, ошибка происходит из-за того, что ты сначала определяешь класс T, а после этого пытаешься создать Generic класс, который имеет тип T.
    17 августа 2011 г. 5:26
    Модератор
  • Кстати, в FW4.0 уже есть встроенный класс комплексных чисел

    Maximys33, поясните цель ваших манипуляций. Лишь бы где вставить дженерик?

    И кстати, generics в C# это совсем не шаблоны C++, у них масса отличий.

    17 августа 2011 г. 8:24
    Отвечающий
  • Нельзя, точно, совсем никак.

    Могу обнадежить - в исходниках 4-го дотнета есть намеки на будущую поддержку операций для генериков, в виде закомментированных кусков типа:

      public struct Double : IComparable, IFormattable, IConvertible 
        , IComparable<Double>, IEquatable<Double>
    ///   , IArithmetic<Double> 
    
    


    и закомментированных реализаций интерфейса для стандартных типов. В исходниках 3.5.1 этих кусков кода не было.

    Но раньше 5-го C# поддержки со стороны компилятора точно не будет.

     

     


    My blog | My Favorite Project
    • Помечено в качестве ответа Maximys33 20 августа 2011 г. 8:26
    17 августа 2011 г. 11:53
    Модератор
  • Нельзя, точно, совсем никак.

    My blog | My Favorite Project

    Жаль, я всегда считал язык C# "сыном" языка C++, думал что он мало того что унаследовал все плюсы C++, но и обзавелся новыми возможностями - я ошибался, конечно C# в немалом количестве вопросов превосходит C++, но у него есть значительные недостатки.

    Ulcer, перешел по предложенной ссылке, скачал "MiscUtil.DLL", который добавил в проект, методом "Ctrl+C => Ctrl+V" перенес предложенную реализацию комплексного числа в свой проект, компиляция прошла успешно:

        static void Main(string[] args)
        {
          Complex<Double> tmp1=new Complex<Double>(1,2);
          Complex<Double> tmp2 = new Complex<Double>(3, 4);
          Complex<Double> tmp3 = tmp1 + tmp2; //строка 5
        }
    
    но на строке 5 вылетает исключение: "FileNotFoundException: Невозможно загрузить файл или сборку "MiscUtil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d3c42c4bfacf7596" или один из зависимых от них компонентов. Не удается найти указанный файл.", хотя данная DLL'ка была скопирована VS2010 в папку с исполняемым файлом программы.

    17 августа 2011 г. 12:23
    1. Выкачал MiscUtil-r285.dll;
    2. Переименовал выкачанный файл в MiscUtil.dll (Убрал из названия -r285);
    3. Создал новое консольное приложение;
    4. Подключил ссылку на переименованный файл;
    5. Добавил в проект класс, скопировал туда код преложенный Скитом.

    Все работает, исключений нет.

        static void Main(string[] args)
        {
          Complex<Double> tmp1 = new Complex<Double>(1, 2);
          Complex<Double> tmp2 = new Complex<Double>(3, 4);
          Complex<Double> tmp3 = tmp1 + tmp2; //строка 5
          Console.WriteLine("Значение после сложения: {0}", tmp3);
          Console.ReadLine();
        }
    


     

    • Помечено в качестве ответа Abolmasov Dmitry 6 сентября 2011 г. 16:35
    17 августа 2011 г. 13:12
    Модератор
  • Генерики в C# - это не аналог шаблонов в C#. Просто синтаксис похож.
    My blog | My Favorite Project
    17 августа 2011 г. 13:44
    Модератор