MSalters schreef op dinsdag 9 juli 2019 @ 15:08:
Als je in C# leert over excepties, en wat er gebeurt wanneer je ze niet vangt, kijk dan ook naar "using" en "finally". Met name de "finally" kan verrassed zijn. Het effect van een "finally" hangt af van een "catch" elders. Dat kan zelfs een catch in een heel andere file zijn. Als je applicatie crasht omdat er helemaal geen catch is, dan werkt de finally ook niet meer.
En om het verwarrend te maken: "finally" runt vóór de "catch".
Dit is gewoon niet waar. Een "finally" runt ná de "catch".
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
| try
{
Console.WriteLine("try");
throw new Exception("Oops");
}
catch (Exception ex)
{
Console.WriteLine("catch");
}
finally
{
Console.WriteLine("finally");
} |
Geeft gewoon netjes de output die je verwacht.
Het enige waar je rekening mee moet houden is dat dit per try-catch blok geldt. Op het moment dat je de try-catch blokken (indirect) nested maakt, blijft de volgorde gewoon hetzelfde. Alleen gebeurt de "inner finally" vóór de outer catch, maar dat is ook logisch.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| try
{
Console.WriteLine("outer try");
try
{
Console.WriteLine("inner try");
throw new Exception("Oops");
}
catch (Exception ex)
{
Console.WriteLine("inner catch");
throw ex; // opzettelijke rethrow
}
finally
{
Console.WriteLine("inner finally");
}
}
catch (Exception ex)
{
Console.WriteLine("outer catch");
}
finally
{
Console.WriteLine("outer finally");
} |
Geeft dus zoals je verwacht:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
Als het de exception niet zou rethrowen, wordt de outer catch niet aangeroepen maar de outer finally wél. Zou je het inner catch block weglaten, dan heb je het zelfde effect als wanneer je zou rethrowen in een catch.
Ook als je nested een exception throwed, maar deze nergens catched, worden alle finally blokken wel aangeroepen. Ondanks dat de applicatie vervolgens wel crashed.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("try");
throw new Exception("Oops"); // uncaught
}
finally
{
Console.WriteLine("finally");
}
}
} |
Geeft dus als output:
try
Unhandled Exception: System.Exception: Oops at ….
finally