В Delphi IDE, как быстро определить местоположение открытого non-project-related файла?

Поскольку я чувствовал, что эти ответы только коснулись поверхности, я попытался копать немного глубже.

Итак, что мы действительно хотим сделать, это что-то, что не компилируется, скажем:

// Won't compile... damn
public static void Main()
{
    try
    {
        throw new ArgumentOutOfRangeException();
    }
    catch (ArgumentOutOfRangeException)
    catch (IndexOutOfRangeException) 
    {
        // ... handle
    }

Причина, по которой мы этого хотим, заключается в том, что мы не хотим, чтобы обработчик исключений перехватывал то, что мы нужно позже в процессе. Конечно, мы можем поймать исключение и проверить, что делать, если «да», но давайте будем честными, мы этого не хотим. (FxCop, проблемы отладчика, уродливость)

Так почему же этот код не скомпилируется - и как мы можем взломать его таким образом, что он будет?

Если мы посмотрим на код, то, что мы действительно хотели бы сделать, это перезвонить. Однако, согласно MS Partition II, блоки обработчиков исключений IL не будут работать таким образом, что в этом случае имеет смысл, поскольку это подразумевает, что объект «исключения» может иметь разные типы.

Или, чтобы записать это в коде, мы просим компилятор сделать что-то вроде этого (ну, это не совсем правильно, но я думаю, это самая близкая вещь):

// Won't compile... damn
try
{
    throw new ArgumentOutOfRangeException();
}
catch (ArgumentOutOfRangeException e) {
    goto theOtherHandler;
}
catch (IndexOutOfRangeException e) {
theOtherHandler:
    Console.WriteLine("Handle!");
}

Причина то, что это не скомпилируется, совершенно очевидно: какой тип и значение будет иметь объект $ exception (которые здесь хранятся в переменных 'e')? Мы хотим, чтобы компилятор справился с этим, отметив, что общим базовым типом обоих исключений является «Исключение», используйте его для переменной, содержащей оба исключения, а затем обрабатывайте только два захваченных исключения. Способ, которым это реализовано в IL, является «фильтром», который доступен в VB.Net.

Чтобы заставить его работать в C #, нам нужна временная переменная с правильным базовым типом «Exception». Чтобы контролировать поток кода, мы можем добавить несколько веток. Вот что:

    Exception ex;
    try
    {
        throw new ArgumentException(); // for demo purposes; won't be caught.
        goto noCatch;
    }
    catch (ArgumentOutOfRangeException e) {
        ex = e;
    }
    catch (IndexOutOfRangeException e) {
        ex = e;
    }

    Console.WriteLine("Handle the exception 'ex' here :-)");
    // throw ex ?

noCatch:
    Console.WriteLine("We're done with the exception handling.");

Очевидными недостатками этого являются то, что мы не можем правильно перебросить, и, давайте будем честными, это довольно уродливое решение. Уродство можно немного исправить, выполнив удаление ветвей, что делает решение немного лучше:

Exception ex = null;
try
{
    throw new ArgumentException();
}
catch (ArgumentOutOfRangeException e)
{
    ex = e;
}
catch (IndexOutOfRangeException e)
{
    ex = e;
}
if (ex != null)
{
    Console.WriteLine("Handle the exception here :-)");
}

Остается только «перебросить». Чтобы это работало, нам нужно иметь возможность выполнять обработку внутри блока «catch» - и единственный способ выполнить эту работу - перехватывать объект «Exception».

На данный момент, мы можем добавить отдельную функцию, которая обрабатывает различные типы исключений, используя разрешение перегрузки, или обрабатывает исключение. Оба имеют недостатки. Для начала вот способ сделать это с помощью вспомогательной функции:

private static bool Handle(Exception e)
{
    Console.WriteLine("Handle the exception here :-)");
    return true; // false will re-throw;
}

public static void Main()
{
    try
    {
        throw new OutOfMemoryException();
    }
    catch (ArgumentException e)
    {
        if (!Handle(e)) { throw; }
    }
    catch (IndexOutOfRangeException e)
    {
        if (!Handle(e)) { throw; }
    }

    Console.WriteLine("We're done with the exception handling.");

И другое решение - перехватить объект Exception и обработать его соответствующим образом. Наиболее буквальный перевод для этого, основанный на контексте выше, является следующим:

try
{
    throw new ArgumentException();
}
catch (Exception e)
{
    Exception ex = (Exception)(e as ArgumentException) ?? (e as IndexOutOfRangeException);
    if (ex != null)
    {
        Console.WriteLine("Handle the exception here :-)");
        // throw ?
    }
    else 
    {
        throw;
    }
}

Итак, сделаем вывод:

  • Если мы не хотим перебрасывать, мы могли бы рассмотрите возможность обнаружения правильных исключений и временного их хранения.
  • Если обработчик прост, и мы хотим повторно использовать код, лучшим решением, вероятно, будет введение вспомогательной функции.
  • Если мы хотим перебросить, у нас нет другого выбора, кроме как поместить код в обработчик перехвата 'Exception', который сломает FxCop и необработанные исключения вашего отладчика.
10
задан Jamo 24 June 2009 в 20:12
поделиться

4 ответа

В Delphi 2009 вы можно навести курсор на вкладку в верхней части кода.

17
ответ дан 3 December 2019 в 13:18
поделиться

У Эрики хороший ответ. Вот еще лучший вариант: вы можете заставить Delphi открыть папку Windows и выделить файл за вас. Вот как это настроить:

Меню инструментов -> Инструменты настройки -> Добавить

Title: Explore
Program: Explorer.exe
Working dir: <leave blank>
Parameters: /select, $EDNAME

Это простой небольшой трюк, который может быть очень удобен, если вы хотите найти файл.

РЕДАКТИРОВАТЬ: Одно примечание: если в настоящее время у вас есть окно проводника Windows, открытое для папки, в которой находится файл, в XP оно активирует окно, но не выбирает файл. В Vista и Win7 откроется новая копия окна.

32
ответ дан 3 December 2019 в 13:18
поделиться

Если вы установите CNPack , бесплатный плагин Delphi, вы также можете щелкнуть правой кнопкой мыши вкладку, и вам будет предложено всплывающее меню, которое включает в себя возможность открыть отредактированный файл в проводнике (очень похоже на трюк с инструментами Мейсона).

5
ответ дан 3 December 2019 в 13:18
поделиться

Обычно Файл-> Сохранить как по умолчанию также используется правильная папка.

Например, если вы поместите курсор внутри имени модуля и нажмете Ctrl-Enter (что, кстати, работает даже если программа запущена в отладчике, а Ctrl-Click не работает) и выполните команду File-> Save As, вы попадете в нужную папку.

По крайней мере, я всегда так делал - прежде чем изучать два новых хитрости здесь :)

3
ответ дан 3 December 2019 в 13:18
поделиться