Что такое управляемый C++, эквивалентный оператору using в C#

Как можно написать следующий код C# в управляемом C++

void Foo()
{
    using (SqlConnection con = new SqlConnection("connectionStringGoesHere"))
    {
         //do stuff
    }
}

Разъяснение: Для управляемых объектов.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
23
0
17 123
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Если вас беспокоит ограничение времени жизни переменной, а не автоматическое удаление, вы всегда можете просто поместить ее в отдельную область:

void Foo()
{
    {
        SqlConnection con = new SqlConnection("connectionStringGoesHere");
        // do stuff
        // delete it before end of scope of course!
    }
}

Это не вызовет ни деструктора в конце области видимости, ни Dispose (). В этом смысле он имеет тот же эффект, что и в C#.

Christian.K 04.12.2008 10:31

Да, ты прав. Не будет. Я предполагал, что это будет сделано в части «что-то делать». Все, что я указывал, это то, что к con нельзя получить доступ за пределами этой новой области.

Mike Hall 07.12.2008 01:01

Для этого в Managed C++ просто используйте семантику стека.

void Foo(){
   SqlConnection con("connectionStringGoesHere");
    //do stuff
}

Когда con выходит за пределы области видимости, вызывается «Деструктор», то есть Dispose ().

Ответ принят как подходящий

Предполагая, что вы имеете в виду C++ / CLI (а не старый управляемый C++), у вас есть следующие варианты:

(1) Имитируйте using-Block с использованием автоматических / основанных на стеке объектов:

{
  SqlConnection conn(connectionString);
}

Это вызовет деструктор объекта "conn", когда закончится следующий включающий блок. Не имеет значения, является ли это закрывающей функцией или блоком, который вы вручную добавляете для ограничения области действия.

(2) Явно вызовите «Dispose», т. Е. Уничтожьте объект:

SqlConnection^ conn = nullptr;
try
{
  conn = gcnew SqlConnection(conntectionString);

}
finally
{
  if (conn != nullptr)
    delete conn;
}

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

Гарантированно ли первый синтаксис (с использованием фигурных скобок для ограничения области действия) вызовет Dispose, даже если вы покидаете область действия, создав исключение? Я не думал, что это так, но, конечно, мог ошибаться.

Coderer 04.12.2008 18:08

Да, это гарантировано. Действительно, идея здесь. Деструкторы объектов, выделенных стеком, вызываются, когда закрывающая область действия заканчивается (регулярно или преждевременно из-за исключения) - на самом деле это не имеет ничего общего с управляемыми или нет. Так же и в машинном коде.

Christian.K 05.12.2008 08:40

@ Christian.K, вы уверены, что "если вы не передадите ссылку в другое место"? Я думаю, что пример (1) подойдет даже в этом случае.

JoelFan 07.11.2011 17:38

@JoelFan Честно говоря, я не могу вспомнить, что я здесь изначально имел в виду ;-) Конечно, вы правы: вы также можете передать объект из (1) в другие места. Я мог только предположить, что во втором случае вы также можете «передать возможность» удалить объект в другое место (т.е. позволить кому-то другому взять на себя управление им на протяжении всей жизни).

Christian.K 08.11.2011 09:33

Следует отметить, что когда var выходит за пределы области видимости, это в очереди для GC, но фактический GC может произойти «позже». Таким образом, если важно, чтобы очистка произошла до того, как вы потеряете область видимости, вы захотите сделать это явно, вместо того, чтобы ждать деструктора / финализатора. Недавно у меня был пример этого, когда я писал в файловый поток, а не вызывал явно stream.Close (). Я обнаружил, что поток не был полностью сброшен до «некоторого более позднего времени» (т.е. когда запускался сборщик мусора), и это вызывало проблемы. Решением было добавить явный вызов stream.Close () до того, как поток выйдет за пределы области видимости.

dlchambers 17.11.2011 21:31

@dlchambers У меня здесь нет практического опыта, но AFAIK деструкторы детерминированы в C++ / CLI. Т.е. когда вызывается деструктор, на самом деле вызывается Dispose. Так что, если у вас есть тип, который "правильно" реализует IDisposable, все будет в порядке. Т.е. время фактического GC, который не имеет ничего общего с Dispose как таковой, не имеет значения, потому что фактическая очистка происходит (детерминированная) в той точке кода, которую вы ожидаете («var выходит за рамки»).

Christian.K 18.11.2011 10:01

На самом деле, в родном C++ деструктор гарантированно будет вызываться только в случае обнаружения исключения - stackoverflow.com/q/8311457/986 (хотя, очевидно, если он не пойман, приложение все равно выйдет из строя).

Mark Ingram 02.02.2015 15:05

Я люблю это. Как мне заставить C# и VB.net сделать это !?

Brain2000 04.12.2018 22:30

Вы можете сделать что-нибудь похожий в стиле auto_ptr:

void foo()
{
    using( Foo, p, gcnew Foo() )
    {
        p->x = 100;
    }
}

со следующим:

template <typename T>
public ref class using_auto_ptr
{
public:
    using_auto_ptr(T ^p) : m_p(p),m_use(1) {}
    ~using_auto_ptr() { delete m_p; }
    T^ operator -> () { return m_p; }
    int m_use;
private:
    T ^ m_p;
};

#define using(CLASS,VAR,ALLOC) \
    for ( using_auto_ptr<CLASS> VAR(ALLOC); VAR.m_use; --VAR.m_use)

Для справки:

public ref class Foo
{
public:
    Foo() : x(0) {}
    ~Foo()
    {
    }
    int x;
};
#include <iostream>

using namespace std;


class Disposable{
private:
    int disposed=0;
public:
    int notDisposed(){
        return !disposed;
    }

    void doDispose(){
        disposed = true;
        dispose();
    }

    virtual void dispose(){}

};



class Connection : public Disposable {

private:
    Connection *previous=nullptr;
public:
    static Connection *instance;

    Connection(){
        previous=instance;
        instance=this;
    }

    void dispose(){
        delete instance;
        instance = previous;
    }
};

Connection *Connection::instance=nullptr;


#define using(obj) for(Disposable *__tmpPtr=obj;__tmpPtr->notDisposed();__tmpPtr->doDispose())

int Execute(const char* query){
    if (Connection::instance == nullptr){
        cout << "------- No Connection -------" << endl;
        cout << query << endl;
        cout << "------------------------------" << endl;
        cout << endl;

        return -1;//throw some Exception
    }

    cout << "------ Execution Result ------" << endl;
    cout << query << endl;
    cout << "------------------------------" << endl;
    cout << endl;

    return 0;
}

int main(int argc, const char * argv[]) {

    using(new Connection())
    {
        Execute("SELECT King FROM goats");//out of the scope
    }

    Execute("SELECT * FROM goats");//in the scope

}

Другие вопросы по теме