2008-12-03 20 views

Respuesta

31

Suponiendo que quiere decir C++/CLI (no el viejo C++ administrado), las siguientes son las opciones:

(1) Mimic un uso-bloque con el uso de objetos automáticos/stackbased:

{ 
    SqlConnection conn(connectionString); 
} 

Esto llamará al Destructor del Objeto "conn" cuando el siguiente bloque envolvente finalice. No importa si esta es la función adjunta o si se agrega manualmente un bloque para limitar el alcance.

(2) Explícitamente llamar "eliminar", es decir, destrucción del objeto:

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

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

El primero sería el reemplazo directo para el "uso". El segundo es una opción, por lo general no tendrá que hacerlo a menos que, opcionalmente, pase la referencia a otro lugar.

+0

¿La primera sintaxis (utilizando llaves desnudas para limitar el alcance) garantiza llamar a Dispose aunque abandone el alcance lanzando una excepción? No pensé que ese fuera el caso, pero por supuesto podría estar equivocado. – Coderer

+0

Sí, está garantizado. De hecho esa es la idea aquí. Los descriptores de los objetos asignados a la pila se invocan cuando finaliza el alcance adjunto (ya sea de forma regular o prematura por una excepción), en realidad eso no tiene nada que ver con la gestión o no. También es así en código nativo. –

+0

@ Christian.K, ¿está seguro de "a menos que, opcionalmente, pase la referencia a otro lugar"? Creo que ese ejemplo (1) estaría bien incluso en ese caso. – JoelFan

-2

Si usted está preocupado por la limitación de la vida útil de la variable en lugar de la eliminación automática, siempre puede ponerlo en su propio ámbito:

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

Esto hará ninguna llamada el destru ctor al final del alcance, ni se llamará a "Dispose()". Es ese sentido que tiene el mismo efecto que en C#. –

+0

Sí, estás en lo correcto. No lo hará. Supuse que eso se haría en la parte "hacer cosas". Todo lo que estaba señalando es que no se puede acceder a la estafa fuera de ese nuevo alcance. –

4

A a la de C++ administrada sólo tiene que utilizar la semántica de la pila.

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

Cuando se sale de alcance, se llama "Destructor", es decir, Dispose().

+0

+1, http://en.wikipedia.org/wiki/Resource_acquisition_is_initialization – orip

2

Se podía hacer algo similares en un estilo auto_ptr:

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

con lo siguiente:

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) 

Como referencia:

public ref class Foo 
{ 
public: 
    Foo() : x(0) {} 
    ~Foo() 
    { 
    } 
    int x; 
}; 
0
#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 

} 
Cuestiones relacionadas