¿Por qué no hay RAII en .NET?

Siendo principalmente un desarrollador de C ++ la ausencia deRAII (La adquisición de recursos es la inicialización) En Java y .NET siempre me ha molestado. El hecho de que la responsabilidad de la limpieza se traslada del escritor de clase a su consumidor (por medio detry finally o .NET'susing construir) parece ser marcadamente inferior.

Veo por qué en Java no hay soporte para RAII ya que todos los objetos se encuentran en el montón y el recolector de basura no admite la destrucción determinista, pero en .NET con la introducción de tipos de valor (struct) tenemos el candidato (aparentemente) perfecto para RAII. Un tipo de valor que se crea en la pila tiene un alcance bien definido y se puede usar la semántica del destructor de C ++. Sin embargo, el CLR no permite que un tipo de valor tenga un destructor.

Mis búsquedas aleatorias encontraron un argumento de que si un tipo de valor esen caja cae bajo la jurisdicción del recolector de basura y, por lo tanto, su destrucción se vuelve no determinista. Siento que este argumento no es lo suficientemente fuerte, los beneficios de RAII son lo suficientemente grandes como para decir que un tipo de valor con un destructor no puede ser encuadrado (o usado como un miembro de la clase).

Para acortar una larga historia mi pregunta es: ¿hay alguna otra razón por la que los tipos de valor no puedan utilizarse para introducir RAII en .NET? (¿O crees que mi argumento sobre las ventajas obvias de RAII es defectuoso?)

Editar: No debí haber formulado la pregunta con claridad, ya que las primeras cuatro respuestas no entendieron nada. yosaber acerca deFinalize y sus características no deterministas, sé de lausing construyo y siento que estas dos opciones son inferiores a RAII.using es una cosa más que el consumidor de una clase debe recordar (cuántas personas se olvidaron de poner unaStreamReader en unusing ¿bloquear?). Mi pregunta es filosófica sobre el diseño del lenguaje, ¿por qué es así y puede mejorarse?

Por ejemplo, con un tipo de valor genérico determinista destructivo puedo hacer queusing ylock palabras clave redundantes (alcanzables por clases de biblioteca):

    public struct Disposer<T> where T : IDisposable
    {
        T val;
        public Disposer(T t) { val = t; }
        public T Value { get { return val; } }
        ~Disposer()  // Currently illegal 
        {
            if (val != default(T))
                val.Dispose();
        }
    }

No puedo evitar terminar con una cita apropiada que una vez vi pero que actualmente no puedo encontrar su origen.

Puedes tomar mi destrucción determinista cuando mi mano fría y muerta se salga del alcance. -Luego

Respuestas a la pregunta(6)

Su respuesta a la pregunta