На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Страницы: (4) 1 2 [3] 4  все  ( Перейти к последнему сообщению )  
> C++/CLI vs C# , Ваше мнение.
    Цитата Loviard @
    Ну там действительно не-value объекты можно располагать в стэке.
    На самом деле я наврал конечно, объект будет располагаться все равно в куче, но вести себя будет как объект расположенный в стеке (семантика стека). В конце метода компилером будет вставлен код вызова финализатора объекта. Так что выглядеть это будет так...
    ExpandedWrap disabled
      void Foo()
      {
        SqlConnection connection (myConnString);
        SqlDataReader reader = connection.ExecuteReader();
        // ... работаем
      } // вызовутся финализаторы


    Добавлено
    Цитата Loviard @
    В конце метода компилером будет вставлен код вызова финализатора объекта
    Однако я опять наврал :D :D :D Вызовется именно IDisposable.Dispose, просто в C++/CLR он имеет синтаксис деструктора. Вообще там все так интересно построено...

    Вот мой код класса:
    ExpandedWrap disabled
      public ref class A
      {
      public:
          A()
          {
              Console::WriteLine("A::A();");
          }
       
          ~A() // деструктор, а на самом деле Dispose
          {
              Console::WriteLine("A::~A();");
          }//*/
       
          !A() // финализатор
          {
              Console::WriteLine("A::!A();");
          }//*/
       
          void f()
          {
              Console::WriteLine("A::f();");
          }
      };


    А вот то, что из него сотворил компилятор:
    (Рефлектор пока только MC++ знает :( )
    ExpandedWrap disabled
      public __gc class A : public IDisposable
      {
          // Methods
          private: void __gc* !A() // компилер превратил в обычный метод, добавил возвращаемый тип, хотя в коде синтаксис этого не требует...
          {
              Console::WriteLine(S"A::!A();");
          }
       
          public: A()
          {
              Console::WriteLine(S"A::A();");
          }
       
          private: void __gc* ~A()
          {
              Console::WriteLine(S"A::~A();");
          }
       
          public: sealed override void __gc* Dispose()
          {
              this->Dispose(true);
              GC::SuppressFinalize(this);
          }
       
          protected: virtual void __gc* Dispose([MarshalAs(UnmanagedType::U1)] Boolean __gc* flag1)
          {
              if (flag1)
              {
                  this->~A();
              }
              else
              {
                  try
                  {
                      this->!A();
                  }
                  finally
                  {
                      base->Finalize();
                  }
              }
          }
       
          public: void __gc* f()
          {
              Console::WriteLine(S"A::f();");
          }
       
          protected: override void __gc* Finalize()
          {
              this->Dispose(false);
          }
       
      };


    Дописав в класс "деструктор" ~A() компилер автоматически порождает мой класс от IDisposable и добавляет код его реализации...
      Loviard, thx. Сбор мусора как был недетерминированым таким и остался по своей сути, ожидать чего то другого было бы странно при размещении объектов в управляемой куче.
        А вот реализация метода f(), в котором я деструктор проверял:
        мой код:
        ExpandedWrap disabled
          void f()
          {
              A a;
              a.f();
          }


        Рефлектор:
        ExpandedWrap disabled
          public private: static void __gc* modopt(CallConvCdecl __gc*) f()
          {
              A __gc* a = 0;
              A __gc* modopt(IsConst __gc*) a2 = __gc new A();
              try
              {
                  a = a2;
                  a->f();
              }
              fault
              {
                  a->Dispose();
              }
              a->Dispose();
          }
        Вообщем ужос :) Объект конечно удален не будет, но путем нескольких извратов компилер вызовет Dispose...
          Loviard, вот смотри какая любопытная фича, при выходе из области видимости объекта A,

          Например код метода f в классе B

          ExpandedWrap disabled
                void f()
                {
                    A a;
                    a.f();
                }


          вызывается его деструктор, но не Dispose, а это наталкивает на одну очень интересную, на мой взгляд мысль, что если пользоваться "семантикой стека" с объектом вроде SqlConnection, то это в конечном итоге, привидет к эффекту достигаемому, когда Close или Dispose вообще явно не вызываются. Как следствие Close отработает при вызове Dispose тогда когда этот объект будет размещен в очередь для выполнения финалайзера... а это произойдет только тогда когда сборщик мусора определит, что объект является мусором. При этом реальное освобождение памяти вообще произойдет при следующем проходе GC.

          Добавлено
          Loviard ты опередил, я только хотел посмотреть во-что это скомпилится. Оказывается Dispose таки вроде как вызывается.
            Не... при выходе из метода вызовется то как раз Dispose, просто в С++/CLI по синтакису Dispose является деструктором (а финалайзер отдельно). Более того, они как-то странно это сделали. Ты можешь отнаследовать класс от IDisposable, но компилер запретит тебе написать метод с названием Dispose. Тебе только можно написать метод ~A() ...А компилер сам реализetn Dispose и вызовет в нем ~A() как показано выше. А при выходе из метода вызовет именно IDisposable.Dispose
              Цитата Loviard @
              компилер вызовет Dispose...


              И закроет соединение:
              Вот код из SqlConnection

              ExpandedWrap disabled
                protected: override void __gc* Dispose(Boolean __gc* disposing)
                {
                    if (disposing)
                    {
                        this->_userConnectionOptions = 0;
                        this->_poolGroup = 0;
                        this->Close();
                    }
                    this->DisposeMe(disposing);
                    base->Dispose(disposing);
                }
              Сообщение отредактировано: juice -
                Цитата juice @
                Loviard ты опередил, я только хотел посмотреть во-что это скомпилится. Оказывается Dispose таки вроде как вызывается.
                :D :D :D Тайный заговор Микрософта раскрыт...
                  Цитата Loviard @
                  Более того, они как-то странно это сделали. Ты можешь отнаследовать класс от IDisposable, но компилер запретит тебе написать метод с названием Dispose.

                  Это очевидно помоему, нельзя и рыбу есть и на велосипеде кататься :)
                    Ну и само собой вполне корректно работает следующая ситуация, что сразу сводит на нет все безопасность:
                    ExpandedWrap disabled
                      A^ f()
                      {
                        A a;
                        a.f();
                        return %a;
                      }
                       
                      void g()
                      {
                        A^ a = f();
                        a.f(); // !!! все вполне корректно :)
                      }


                    Вот вам и область видимости переменной :D :D :D
                      Цитата Loviard @
                      Ну и само собой вполне корректно работает следующая ситуация, что сразу сводит на нет все безопасность:
                      ExpandedWrap disabled
                        A^ f()
                        {
                          A a;
                          a.f();
                          return %a;
                        }
                         
                        void g()
                        {
                          A^ a = f();
                          a.f(); // !!! все вполне корректно :)
                        }


                      Вот вам и область видимости переменной :D :D :D

                      Угу :) На сарае написано XXX, а там дрова лежат... вот так и тут по ходу выходит ... :)
                        Цитата Loviard @
                        еще раз повторяю свой вопрос.

                        Чего ты прикидываешься?
                        Несовместимы - это когда ты пишешь конструкцию ANSI C++, а она в режиме С++/CLI превращается в конструкцию С++/CLI - т.е. теряется возможность в одной программе использовать конструкции из обоих языков так, как они задумывались. Но ведь это не так, а значит - языки совместимы.

                        Цитата juice @
                        Цитата Loviard @
                        Ну и само собой вполне корректно работает следующая ситуация, что сразу сводит на нет все безопасность:
                        ExpandedWrap disabled
                          A^ f()
                          {
                            A a;
                            a.f();
                            return %a;
                          }
                           
                          void g()
                          {
                            A^ a = f();
                            a.f(); // !!! все вполне корректно :)
                          }


                        Вот вам и область видимости переменной :D :D :D

                        Угу :) На сарае написано XXX, а там дрова лежат... вот так и тут по ходу выходит ... :)

                        Да не, походу выходит, что управляемые программисты на ворнинги внимания обращают.. :blink:
                        Ну, тогда Бог с вами, возвращайте указатели на локальные автоматические объекты, если вам так хочется, а потом плюйтесь на язык.
                        Адью.
                        Сообщение отредактировано: Hryak -
                          Hryak, да мы не плюемся. Ты по моему не правильно толкуешь. Я например считаю C++/CLI вполне оптимальным выбором в некоторых ситуациях. Просто я думал ты волшебник и покажешь как объект SqlConnection поместить на стеке, а не в куче, а потом еще и коректно освободить память не вызывая Close. А ты просто описался видимо или думал о "стеке" рассмотренном выше.
                            Цитата juice @
                            Просто я думал ты волшебник и покажешь как объект SqlConnection поместить на стеке

                            Читаем внимательно в C++/CLI vs C# (сообщение #1945345)
                            Цитата Hryak @
                            И возня с using лаконичнее возможности размещения объектов "на стеке" в C++/CLI?

                            Кавычки видим? Я же их не случайно поставил, я прекрасно знаю, что такие объеты по-любому размещаются в управляемой куче, речь шла именно про семантику стека, а не про сам стек.

                            Добавлено
                            Цитата juice @
                            Я например считаю C++/CLI вполне оптимальным выбором в некоторых ситуациях.

                            Чтобы была ясность - я не считаю, что C++/CLI - оптимальный выбор во всех ситуациях. Я просто защищаю конкретную уникальную фичу этого языка, которую вы недооцениваете, имхо.
                              Цитата Hryak @
                              Чего ты прикидываешься?
                              Ты давай повежливее... Ты сам-то не прикидываешься? - ты понял что я имел в виду, более того, я это потом еще и объяснил подробно. В общем ты просто придираешься к словам.

                              Цитата Hryak @
                              Да не, походу выходит, что управляемые программисты на ворнинги внимания обращают..
                              Ну, тогда Бог с вами, возвращайте указатели на локальные автоматические объекты, если вам так хочется, а потом плюйтесь на язык.
                              Адью.
                              Ты чего кипятишься? Конечно я заметил варнинг, но это просто костыль компилятора. Потому-что код, который я привел вполне корректный. Объект располагается в управляемой куче, я увеличил количество ссылок на него, поэтому могу без задних мыслей его использовать в другом методе.

                              Цитата Hryak @
                              Чтобы была ясность - я не считаю, что C++/CLI - оптимальный выбор во всех ситуациях. Я просто защищаю конкретную уникальную фичу этого языка, которую вы недооцениваете, имхо.
                              Это не та фича, которая повлияла бы хоть на какое-то решение в его пользу. Фичи, ради которых, его действительно стоит использовать, я приводил выше...
                                Цитата Loviard @
                                Это не та фича, которая повлияла бы хоть на какое-то решение в его пользу.

                                Согласен.

                                По сабжу. ИМХО, вариант с auto_handle, выглядит естественней и действительно является классной фичей, равноценно-удобного аналога которого в шарпе дейтсвительно нет. Покрайней мере, на мой неискушенный взгляд, код в данном контексте получается ясный и явно демонстрирует намерения разработчика.
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (4) 1 2 [3] 4  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0491 ]   [ 15 queries used ]   [ Generated: 8.11.25, 22:22 GMT ]