Dot-Net

為什麼 .NET 中沒有 RAII?

  • October 6, 2008

作為一名 C++ 開發人員,Java 和 .NET 中缺少RAII(資源獲取即初始化)一直困擾著我。清理的責任從類編寫者轉移到其消費者(通過try finally.NET 的using構造)這一事實似乎明顯遜色。

我明白為什麼在 Java 中不支持 RAII,因為所有對像都位於堆上,而垃圾收集器本身不支持確定性銷毀,但在 .NET 中引入值類型(struct)我們有(似乎) RAII 的完美候選人。在堆棧上創建的值類型具有明確定義的範圍,並且可以使用 C++ 解構子語義。但是,CLR 不允許值類型具有解構子。

我的隨機搜尋發現了一個論點,即如果一個值類型被裝箱,它就屬於垃圾收集器的管轄範圍,因此它的銷毀變得不確定。我覺得這個論點不夠有力,RAII 的好處大到足以說明帶有解構子的值類型不能被裝箱(或用作類成員)。

長話短說,我的問題是:是否有任何其他原因不能使用值類型來將 RAII 引入 .NET?(或者你認為我關於 RAII 明顯優勢的論點有缺陷嗎?)

**編輯:**我一定沒有清楚地表達這個問題,因為前四個答案沒有抓住重點。我知道它的非確定性Finalize特徵,我知道using構造,我覺得這兩個選項不如 RAII。using類的消費者還必須記住一件事(有多少人忘記將 aStreamReader放在一個using塊中?)。我的問題是關於語言設計的哲學問題,為什麼它是這樣的,可以改進嗎?

例如,使用通用的確定性可破壞值類型,我可以使usingandlock關鍵字變得多餘(可通過庫類實現):

   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();
       }
   }

我不禁以我曾經看過但目前無法找到其來源的恰當報價作為結尾。

當我冰冷的死手超出範圍時,您可以承擔我的確定性破壞。——匿名

更好的標題是“為什麼 C#/VB 中沒有 RAII”。C++/CLI(託管 C++ 的流產演變)具有與 C++ 完全相同的意義上的 RAII。這只是其他 CLI 語言使用的相同終結模式的語法糖(C++/CLI 的託管對像中的解構子實際上是終結器),但它就在那裡。

您可能會喜歡<http://blogs.msdn.com/hsutter/archive/2004/07/31/203137.aspx>

引用自:https://stackoverflow.com/questions/173670