技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

C#:try-catch-finally句内のreturnの仕様

表題についてjavaでは調査している記事が別にあったのですが、C#だと調査している記事が見つからなかったので、調査してみました。
 
C#でも、try句やcatch句の中でreturnを行った場合、returnする直前にfinally句が実行されるという挙動となります。これはjavaと同じ仕様です。
また、finally句でreturnを記述してreturnを上書きしようとするとビルドエラーになります。javaだと警告止まりのようなので、この点では仕様が異なっています。
 
【調査プログラム】
・Test1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test1
{
    class Test1
    {
        static int Main(string[ ] args)
        {
            try
            {
                Console.WriteLine("try句でreturnします");
                return 1;
            }
            catch
            {
                Console.WriteLine("catch句は通りません");
            }
            finally
            {
                Console.WriteLine("finally句を通ってからreturnします");
            }
            return 0; // ここは通らない
        }
    }
}
 
・Test2.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test2
{
    class Test2
    {
        static int Main(string[ ] args)
        {
            try
            {
                throw new Exception("例外発生");
                Console.WriteLine("try句でreturnする前に例外発生");
                return 1;
            }
            catch
            {
                Console.WriteLine("catch句でreturnします");
                return 2;
            }
            finally
            {
                Console.WriteLine("finally句を通ってからreturnします");
            }
            return 0; // ここは通らない
        }
    }
}
 
・Test3.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test3
{
    class Test3
    {
        static int Main(string[ ] args)
        {
            try
            {
                throw new Exception("例外発生");
                Console.WriteLine("try句でreturnする前に例外発生");
                return 1;
            }
            catch
            {
                Console.WriteLine("catch句でreturnします");
                return 2;
            }
            finally
            {
                Console.WriteLine("finally句でreturnを書くとコンパイルエラー");
                return 3;
            }
            return 0; // ここは通らない
        }
    }
}
 
・Test.bat
@echo off

echo ■Test1
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe Test1.cs>nul
Test1.exe
echo 戻り値:%ERRORLEVEL%
echo;

echo ■Test2
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe Test2.cs>nul
Test2.exe
echo 戻り値:%ERRORLEVEL%
echo;

echo ■Test3
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe Test3.cs
rem Test3.exe
rem echo 戻り値:%ERRORLEVEL%
echo;

pause
 
【調査結果(実行結果)】
■Test1
try句でreturnします
finally句を通ってからreturnします
戻り値:1

■Test2
catch句でreturnします
finally句を通ってからreturnします
戻り値:2

■Test3
Microsoft (R) Visual C# Compiler version 4.7.3062.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.

This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, w
hich is no longer the latest version. For compilers that support newer versions of the C# programming language, see http
://go.microsoft.com/fwlink/?LinkID=533240

Test3.cs(27,17): error CS0157: コントロールが finally 句の本体から出られません。

続行するには何かキーを押してください . . .