Ответ 1
Я попытался декомпилировать сборку, и похоже, что сборка делает некоторую оптимизацию в любом режиме. В частности, изменяется второй способ:
private static void ThrowSomeException(int arg)
{
Console.WriteLine("arg = {0}", arg);
switch (arg)
{
case 0:
{
throw new Exception("Line number = 16");
}
case 1:
{
throw new Exception("Line number = 18");
}
}
throw new Exception("Line number = 20");
}
Это то, что Telerik JustDecompile сообщает мне, как выглядит метод, как в режиме отладки, так и в режиме Release. Очень возможно, что если вы просмотрите необработанную сборку, появится еще одно объяснение, почему это несоответствие существует.
Я не знаю, как продолжить это, но я думаю, что это очень интересная проблема. Я собираюсь отметить свой ответ как Community Wiki, надеясь, что совлокальные усилия могут решить это.
Я провел еще несколько тестов. Я переместил функцию ThrowSomeException() в отдельный класс и сделал ее нестатической, и это ничего не изменило. Затем я немного переписал его, чтобы сначала назначить исключение переменной, а затем выбросить ее отдельно.
internal class Program
{
private static void Main()
{
Test test = new Test();
for (int i = 0; i < 3; i++)
{
try
{
test.ThrowSomeException(i);
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
}
public class Test
{
public void ThrowSomeException(int arg)
{
Console.WriteLine("arg = {0}", arg);
switch (arg)
{
case 0:
{
Exception ex = new Exception("Line number = 36");
throw ex;
}
case 1:
{
Exception ex = new Exception("Line number = 41");
throw ex;
}
default:
{
Exception ex = new Exception("Line number = 46");
throw ex;
}
}
}
}
Вышеприведенный код имеет следующий вывод в режиме отладки:
arg = 0
System.Exception: Line number = 36
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 40
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 1
System.Exception: Line number = 41
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 45
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 2
System.Exception: Line number = 46
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 47
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
В режиме деблокирования второе исключение выбрано из строки 46 вместо 45. Это поведение совместимо для всех версий платформы .NET и всех версий VS. Теперь я попытаюсь сделать это, используя проект VB, чтобы узнать, не имеет значения.
Изменить: используя следующий проект VB в VS 2012:
Module Program
Sub Main()
Dim test As New Test()
For i As Integer = 0 To 2
Try
test.ThrowSomeException(i)
Catch exception As Exception
Console.WriteLine(exception)
End Try
Next
End Sub
End Module
Public Class Test
Public Sub ThrowSomeException(arg As Integer)
Console.WriteLine("arg = {0}", arg)
Select Case arg
Case 0
If True Then
Dim ex As New Exception("Line number = 22")
Throw ex
End If
Case 1
If True Then
Dim ex As New Exception("Line number = 27")
Throw ex
End If
Case Else
If True Then
Dim ex As New Exception("Line number = 32")
Throw ex
End If
End Select
End Sub
End Class
Проблема не возникает и номера строк согласованы.
Я также тестировал исполняемые файлы, сгенерированные выходом напрямую, и нашел еще более веские результаты. Это вывод отладки exe:
arg = 0
System.Exception: Line number = 36
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 40
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 1
System.Exception: Line number = 41
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 45
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 2
System.Exception: Line number = 46
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 47
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
И это вывод из режима выпуска exe:
arg = 0
System.Exception: Line number = 36
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 41
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 1
System.Exception: Line number = 41
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 42
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
arg = 2
System.Exception: Line number = 46
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 37
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 14
Это не тот же результат, что и использование отладчика для его запуска.
Быстрые тесты, похоже, указывают на то, что дополнительные строки между инструкцией exception и throw (в этом случае консоль .writeline() также влияет на результат:
перезаписан переключатель:
switch (arg)
{
case 0:
{
Exception ex = new Exception("Line number = 37");
Console.WriteLine("case 0");
throw ex;
}
case 1:
{
Exception ex = new Exception("Line number = 43");
Console.WriteLine("case 1");
throw ex;
}
default:
{
Exception ex = new Exception("Line number = 49");
Console.WriteLine("case default");
throw ex;
}
}
дает этот выход Release из VS:
arg = 0
case 0
System.Exception: Line number = 37
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 43
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 1
case 1
System.Exception: Line number = 43
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 49
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 2
case default
System.Exception: Line number = 49
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 51
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
и этот вывод из командной строки:
arg = 0
case 0
System.Exception: Line number = 37
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 43
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 1
case 1
System.Exception: Line number = 43
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 45
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 2
case default
System.Exception: Line number = 49
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 39
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
и этот отладочный вывод VS:
arg = 0
case 0
System.Exception: Line number = 37
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 42
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 1
case 1
System.Exception: Line number = 43
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 48
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 2
case default
System.Exception: Line number = 49
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 51
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
И этот вывод из командной строки:
arg = 0
case 0
System.Exception: Line number = 37
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 42
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 1
case 1
System.Exception: Line number = 43
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 48
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15
arg = 2
case default
System.Exception: Line number = 49
bij linenumbertest.Test.ThrowSomeException(Int32 arg) in c:\Users\nate\Docume
nts\Visual Studio 2012\Projects\linenumbertest\Program.cs:regel 51
bij linenumbertest.Program.Main() in c:\Users\nate\Documents\Visual Studio 20
12\Projects\linenumbertest\Program.cs:regel 15