static constructor で例外を出すと同じ例外が使い回される
◆ static constructor はインスタンス作ったり static なプロパティやメソッドアクセス時に実行される
◆ 使わなかったクラスの static constructor は呼ばれない
◆ コンストラクタを実行しないインスタンス作成のときでも呼び出される
◆ 一度 static constructor で例外が起きるとそれ以降ずっと例外になる
◆ static constructor は 1 回目しか実行されない
◆ static consturctor での例外は TypeInitializationException にラップされる
◆ アクセスするたび起きる例外のインスタンスは全部同じもの
◆ 使わなかったクラスの static constructor は呼ばれない
◆ コンストラクタを実行しないインスタンス作成のときでも呼び出される
◆ 一度 static constructor で例外が起きるとそれ以降ずっと例外になる
◆ static constructor は 1 回目しか実行されない
◆ static consturctor での例外は TypeInitializationException にラップされる
◆ アクセスするたび起きる例外のインスタンスは全部同じもの
static constructor の実行タイミング
static constructor は最初にそのクラスを使うときに実行されますstatic なプロパティやメソッドにアクセス また インスタンス生成時に実行されます
public class ThrowException
{
static ThrowException()
{
throw new Exception(text);
}
public ThrowException()
{
}
static public int prop { get; } = 1;
static public int method(int x) => x;
}
// var instance = new ThrowException();
// var instance = ThrowException.prop;
// var instance = ThrowException.method(1);
// var instance = System.Activator.CreateInstance(typeof(ThrowException));
// var instance = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(ThrowException));
どのコメントアウトを解除しても例外です
Reflection で型から作った場合も コンストラクタを実行しないオブジェクト作成でも static なコンストラクタは実行されます
一度例外が起きるとずっと使えない
一度 static constructor で例外が起きると 2 回目のクラスアクセスでは static constructor は実行されずに例外が出ますpublic partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_A(object sender, RoutedEventArgs e)
{
try
{
var a = ThrowException.prop;
}
catch { }
}
private void Button_Click_B(object sender, RoutedEventArgs e)
{
try
{
var b = ThrowException.method(1);
}
catch { }
}
private void Button_Click_C(object sender, RoutedEventArgs e)
{
try
{
var c = new ThrowException();
}
catch { }
}
}
public class ThrowException
{
static ThrowException()
{
var text = "static constructor exception";
Console.WriteLine(text);
throw new Exception(text);
}
public ThrowException()
{
var text = "instance constructor exception";
Console.WriteLine(text);
throw new Exception(text);
}
static public int prop { get; } = 1;
static public int method(int x) => x;
}
最初のボタンを押したときだけ 「static constructor exception」 とメッセージが出ますが それ以降はボタンを押しても何も起きません
2 度目以降は static constructor が実行すらされないので 実行する状況に応じて例外が出ることもある作りになっていると 最初に例外が出てしまうとずっとそのクラスが使えなくなります
例外は共通
一度例外が出ると それ以降のクラスアクセス時に即例外になるわけですが 例外オブジェクトはずっと同じものですstatic constructor での例外は特別な TypeInitializationException という例外クラスにラップされていて その InnerException に static constructor で throw した例外が入っています
throw する例外オブジェクトにテキストを追加していってみます
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_A(object sender, RoutedEventArgs e)
{
try
{
var a = ThrowException.prop;
}
catch (Exception ex)
{
var iex = (CException)ex.InnerException;
iex.text += "a";
Console.WriteLine(iex.text);
}
}
private void Button_Click_B(object sender, RoutedEventArgs e)
{
try
{
var b = ThrowException.method(1);
}
catch (Exception ex)
{
var iex = (CException)ex.InnerException;
iex.text += "b";
Console.WriteLine(iex.text);
}
}
private void Button_Click_C(object sender, RoutedEventArgs e)
{
try
{
var c = new ThrowException();
}
catch (Exception ex)
{
var iex = (CException)ex.InnerException;
iex.text += "c";
Console.WriteLine(iex.text);
}
}
}
public class ThrowException
{
static ThrowException()
{
var text = "static constructor exception";
Console.WriteLine(text);
throw new CException(text);
}
public ThrowException()
{
var text = "instance constructor exception";
Console.WriteLine(text);
throw new CException(text);
}
static public int prop { get; } = 1;
static public int method(int x) => x;
}
public class CException : Exception
{
public CException(string text) : base(text) { }
public string text { get; set; } = "";
}
(a click)
static constructor exception
a
(b click)
ab
(c click)
abc
前回のが残っているので追記されていきます