Подтвердить что ты не робот

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

Как бы кодировать следующий код С# в Managed С++

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

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

4b9b3361

Ответ 1

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

(1) Подражать использованию блока с использованием объектов с автоматическим/стеком:

{
  SqlConnection conn(connectionString);
}

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

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

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

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

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

Ответ 2

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

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

Когда con выходит за рамки, вызывается "Destructor", то есть Dispose().

Ответ 3

Вы можете сделать что-то подобное в стиле 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;
};

Ответ 4

#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

}

Ответ 5

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

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