1. 程式人生 > 其它 >dotnet C# 如果在建構函式丟擲異常 解構函式是否會執行

dotnet C# 如果在建構函式丟擲異常 解構函式是否會執行

假設在某個型別的建構函式裡面丟擲了異常,那麼這個物件的解構函式是否會執行

如下面程式碼

        private void F1()
        {
            try
            {
                _ = new Foo();
            }
            catch
            {
               // 忽略
            }
        }

    class Foo
    {
        public Foo()
        {
            throw new Exception("lindexi is doubi");
        }

        ~Foo()
        {
        }
    }

請問以上程式碼的 ~Foo 是否可以在垃圾回收執行,或者說在建構函式裡面丟擲異常,是否這個物件可以被垃圾回收

試試以下程式碼,然後在 ~Foo 新增斷點

        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            var program = new Program();
            program.F1();

            GC.Collect();
            GC.WaitForFullGCComplete();
            GC.Collect();

            Task.Delay(1000).Wait();

            Console.WriteLine("Hello World!");
        }

其實可以看到,可以進入 ~Foo 的程式碼。原因是在 .NET 執行時,是先創建出物件,然後再呼叫物件的建構函式。而在創建出物件時,此物件就需要被加入垃圾回收,加入垃圾回收,自然就會呼叫到解構函式

那為什麼即使在建構函式裡面丟擲異常,沒有構造成功,也需要在垃圾回收呼叫解構函式。是因為建構函式也不一定是一句話都沒有跑的,例如在建構函式裡面已分配了一些非託管的記憶體,然後再丟擲異常,自然就期望在解構函式可以釋放分配的記憶體,也就是期望呼叫解構函式

本文程式碼還請到 githubgitee 上閱讀程式碼

可以通過如下方式獲取本文的原始碼,先建立一個空資料夾,接著使用命令列 cd 命令進入此空資料夾,在命令列裡面輸入以下程式碼,即可獲取到本文的程式碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 3f16a1492f1d655ad5356e65d476c3c91b129844

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

獲取程式碼之後,進入 HojeneceabuHallwhallhebo 資料夾