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

Как бы один код следующий код C# в управляемом c++

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

Clarificaton: Для управляемых объектов.

5 ответов


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

(1) имитировать с помощью блока с помощью автоматических объектов / stackbased:

{
  SqlConnection conn(connectionString);
}

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

(2) явно вызовите "Dispose", т. е. уничтожьте объект:

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

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

первый будет прямой заменой для "использования". Второй вариант, как правило,вам не нужно будет делать, если вы не передадите ссылку в другое место.


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

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

когда con выходит из области действия, вызывается" деструктор", т. е. Dispose ().


вы могли бы сделать что-то как в стиле 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

}

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

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