2010-04-06 10 views
5

Soy nuevo en .NET ..y estoy confundido con el mecanismo destructor en C# ..Por favor aclararqué método Finalize no pueden anular

en C# destructores son convertidos para finalizar método por el CLR. Si intentamos anularlo (no usando destructor), obtendremos un error Error 2 No anule el objeto. Finalice. En cambio, proporciona un destructor.

Pero parece que la implementación de Object calss en mscorlib.dll ha finalizado definido como anulación protegida void Finalize() {}, entonces ¿por qué no podemos anularlo, para qué función virtual?

¿Por qué es el diseño de esa manera, es que sea consistente con el concepto C++ destructor.

También cuando vamos a la definición de la clase de objeto, no se menciona el método de finalización, entonces, ¿cómo la definición de hmscorlib.dll muestra la función de finalización? Significa que el destructor predeterminado se convierte en el método de finalización.

public class Object 
{  

    public Object(); 
    public virtual bool Equals(object obj);   
    public static bool Equals(object objA, object objB);  
    public virtual int GetHashCode();  
    public Type GetType();  
    protected object MemberwiseClone(); 
    public static bool ReferenceEquals(object objA, object objB); 
    public virtual string ToString(); 
} 

Respuesta

0

Para anular Finalize(), debe utilizar la sintaxis finalizador. La CLI utiliza nombres fijos para ciertas cosas internamente, como todos los constructores instancia con nombre exactamente .ctor, y todos los constructores estáticos nombrado .cctor. Cuando el compilador de C# escribe el ensamblaje de salida, se asegura de usar nombres propios para los elementos que emite, lo que incluye escribir el destructor con el nombre Finalize() en lugar de ~T(). Los compiladores para otros lenguajes .NET también deben seguir estas mismas reglas para su propia semántica.

class A 
{ 
    ~A() { /* ... */ } 
} 

Para el cuándo y el cómo de los finalizadores, busque las muchas otras preguntas aquí que se ocupan de los finalizadores y IDisposable.

+1

Creo que lo entienden y piden una explicación _por qué_. –

4

'¿Por qué es así?
Por decisión de diseño. Probablemente para hacer coincidir con C++ pero realmente no importa.

cómo la definición hmscorlib.dll muestra la función de finalización

Probablemente es una intervención especial en el compilador de C#. Nuevamente, no hace ninguna diferencia práctica.

Si realmente necesita un finalizador, escribir un destructor. Más importante: casi nunca es necesario.

Para ver cómo esta elección arbitraria es: en VB que pueda override Finalize. Y esos dos idiomas pueden muy felizmente usar (y heredar) los demás tipos.

+3

+1 para "casi nunca necesitas". La interfaz 'IDisposable' usualmente es lo que se necesita. –

+0

@Richard, sí, IDisposable clases con frecuencia, pero no siempre tienen un destructor. Tener un destructor sin IDisposable es muy raro (e incluso sospechoso). –

0

Qué significa que el destructor por defecto se convierte para finalizar método

Sí, el valor por defecto (y única) sintaxis destructor en C# es compilado como el método Finalize. Es probable que esto proporcione una sintaxis familiar a los desarrolladores de C++. Consulte Destructors on MSDN para obtener más información.

+1

No hay un destructor predeterminado en C#. –

0

En C++, es necesario el destructor a ser virtual.La razón es que esta es la forma en que se invoca

A a = new B() //where B derived from A 
delete a; 

Un poco oxidado en C++, por lo que me perdone si estoy equivocado. Pero mira, la eliminación se pasa una referencia que puede ser de una clase base.

En C#, no invoca el finalizador. Es invocado internamente por el recolector de basura. No hay ninguna razón para que un recolector de basura esté interesado en qué tipo de referencias se asignaron anteriormente y se dirige directamente al objeto :)

Ahora, el finalizador obtiene la sintaxis de C++. De ahí la confusión.

Lo que otras personas dicen es que, por lo general, no necesita finalización. Esta es la razón por.

Si implementa IDisposable, puede tomar la ayuda de la instrucción "using" para decidir el alcance de la variable y disponerla cuando lo desee. Con la Finalización, el GC toma la decisión de cuándo exactamente se llamará el método. Eso significa que, si necesita liberar recursos, el momento puede ser incorrecto.

Espero que esto ayude.

20

soy nuevo en .NET y estoy confundido con el mecanismo destructor en C#. Por favor aclara

Sure. Estoy de acuerdo en que es confuso.

En C# los destructores se convierten en el método de finalización por CLR.

Correcto. Bueno, yo diría que esto lo hace el compilador C#, no el CLR, pero entiendo lo que quieres decir.

Si tratamos de anularlo (no utilizando destructor), aparecerá un mensaje de error "No anule el objeto.Finalice. En su lugar, proporcione un destructor".

Correcto.

parece que la implementación de la clase de objeto en mscorlib.dll ha Finalizar los definida como protected override void finalize() {}

correcta.

¿por qué no podemos anularlo? Para eso es una función virtual.

Porque entonces no habría dos formas de escribir un destructor. Eso sería confuso. Queremos que haya solo una forma de escribir un destructor.

¿Por qué es así el diseño? ¿Es ser consistente con el concepto de destructor de C++?

Esa es una razón, sí. Hay otras razonesAquí están algunos:

  • Al separar lógicamente los conceptos de "destructor" y "reemplazar el método de finalización" que hacen posible la implementación de los destructores a través de algún otro mecanismo en otros entornos. Esto aún no ha sucedido, pero podría ocurrir que en el futuro escribamos una versión de C# que, por ejemplo, es para construir controladores de dispositivos en un entorno que tiene una semántica de recolector de basura diferente a la semántica de CLR estándar. En ese entorno, la semántica del destructor podría ser más similar a la del destructor de C++ y menos a un finalizador de GC.

  • Los finalizadores son métodos muy muy especiales. No puedes llamarlos como métodos regulares; solo el recolector de basura puede llamarlos. Tienen diferentes reglas de manejo de excepciones. Deben asegurarse de que los finalizadores de la clase base se llamen estrictamente después de los finalizadores de clase derivados. Son tan especiales que parece peligroso exponerlos como métodos como cualquier otro. Si tiene un método simplemente sentado que puede llamar, que puede poner lo que desee, y así sucesivamente, hace que sea fácil olvidar lo especial que es un finalizador. Tener una sintaxis especial enfatiza que este es un código especial.

también cuando vamos a la definición de la clase de objeto, no hay mención del método de finalización, entonces, ¿cómo lo hace la definición mscorlib.dll muestra la función de finalización.

Supongamos que mostramos un método en el navegador de objetos llamado MagicUnicorn, y si intentas llamarlo o anularlo, obtendrás un error que dice "¡no hagas eso!". ¿Por qué molestarse en mostrar el método MagicUnicorn si no puede hacer nada con él? Eso es solo ruido inútil.

Ahora, si desmontas mscorlib entonces, por supuesto, existe el método especial Finalize allí.

Significa que el destructor predeterminado se convierte al método de finalización.

Sí.

+0

¿Hay alguna forma en que el código pueda usar un destructor * correctamente * sin codificar con eficacia los nombres de 'GC.SuppressFinalize()' y 'GC.KeepAlive()'? Si C# proporcionara una sintaxis para invocar tales funciones cuando sea necesario (sin tener que usar nombres específicos del framework), podría ver algún valor en la sintaxis del destructor. Por otro lado, si escribir un objeto autolimpiador apropiado requiere el uso de al menos dos métodos 'GC. *' Específicos del framework, no estoy seguro de qué valor hay para que una pequeña parte del rompecabezas sea específica de langugage. en lugar de específico del marco. ¿Me estoy perdiendo de algo? – supercat

Cuestiones relacionadas