c # использование неназначенной локальной переменной после Try..Catch

#c# #.net #interop

#c# #.net #взаимодействие

Вопрос:

Я использую приведенный ниже код для получения запущенного экземпляра MS Word.

Теперь у меня проблема с компиляцией с использованием неназначенной локальной переменной «oWord»‘

вот мой код:

 Microsoft.Office.Interop.Word._Application oWord ; 

try
{
// Is Word running?
oWord = Marshal.GetActiveObject("Word.Application") as Microsoft.Office.Interop.Word.Application; // ApplicationClass;
}
catch (COMException ce)
{
if (ce.ErrorCode == unchecked((int)0x800401E3))
    // No, Word not in ROT, start a new instance
    oWord = new Microsoft.Office.Interop.Word.Application();
}
// Use instance referened by _WordApp 

oWord.ScreenUpdating = false; // < PROBLEM HERE

object objDefaultBehaviorWord8 = WdDefaultTableBehavior.wdWord8TableBehavior;
object objAutoFitFixed = WdAutoFitBehavior.wdAutoFitFixed;

//MAKING THE APPLICATION VISIBLE
oWord.Visible = Properties.Settings.Default.DebugMode;
oWord.DisplayAlerts = WdAlertLevel.wdAlertsNone;
  

но, на мой взгляд, oWord назначен, я предполагаю, что компилятор просматривает мой блок Try ..Catch и говорит, что у меня неназначенный oWord

Итак, как правильно назначить это?

Комментарии:

1. Microsoft.Office.Interop.Word._Application oWord = null

2. Какое значение oWord имеет значение if false?

Ответ №1:

Возможно, она никогда не будет назначена, если Marshal.GetActiveObject вызов завершится неудачно, но код ошибки — это нечто иное, чем unchecked((int)0x800401E3) .

Вам нужно установить oWord что-то при первом объявлении:

 Microsoft.Office.Interop.Word._Application oWord = null;
  

или

 Microsoft.Office.Interop.Word._Application oWord = new Microsoft.Office.Interop.Word.Application();
  

Я бы, вероятно, сделал последнее. Это также устраняет необходимость в проверке null дальше по строке, что прямо сейчас вам действительно нужно, поскольку вы не выполняете полный прерывание, если в этом блоке try / catch обнаружено исключение.

(Сказав это, если это действительно приведет к запуску Word, если он еще не запущен, выберите первый вариант, а затем убедитесь oWord , что после try / catch значение по-прежнему не равно null.)

Комментарии:

1. Проблема здесь в том, что вы не обрабатываете ошибки COM, кроме MK_E_UNAVAILABLE . Вам нужно что-то с ними сделать. Ваш ответ ведет к null проверкам, но это просто беспорядочно. Особенно когда есть очень простой способ решить проблему.

2. @DavidHeffernan согласился. Ваш ответ — лучший подход.

Ответ №2:

 Microsoft.Office.Interop.Word._Application oWord; 
try
{
    oWord = Marshal.GetActiveObject("Word.Application") as
        Microsoft.Office.Interop.Word.Application;
}
catch (COMException ce)
{
    if (ce.ErrorCode == unchecked((int)0x800401E3))
        oWord = new Microsoft.Office.Interop.Word.Application();
}
oWord.ScreenUpdating = false;
  

Давайте попробуем понять, почему компилятор сообщает вам, что oWord она не может быть назначена после выполнения этого кода.

  1. Если код внутри try выполняется без исключения, то oWord он должен быть назначен.
  2. Или, если этот код выдает исключение, он может быть необработанным, и в этом случае он распространяется за пределы кода выше.
  3. Или, если код в try выдает COMException , он будет перехвачен. Если код ошибки 0x800401E31 затем oWord присваивается.
  4. Или, если код ошибки отличается от 0x800401E3 , то oWord никогда не присваивается.

Мы можем аннотировать ваш код, чтобы продемонстрировать это более наглядно:

 Microsoft.Office.Interop.Word._Application oWord; 
try
{
    oWord = Marshal.GetActiveObject("Word.Application") as
        Microsoft.Office.Interop.Word.Application;
}
catch (COMException ce)
{
    // oWord still not initialized ....
    if (ce.ErrorCode == unchecked((int)0x800401E3))
        oWord = new Microsoft.Office.Interop.Word.Application();
    else
        ; // .... and still not initialized ....
}
oWord.ScreenUpdating = false;
  

На мой взгляд, самый простой способ справиться с этим — повторно создать исключение.

 Microsoft.Office.Interop.Word._Application oWord; 
try
{
    oWord = Marshal.GetActiveObject("Word.Application") as
        Microsoft.Office.Interop.Word.Application;
}
catch (COMException ce)
{
    if (ce.ErrorCode != unchecked((int)0x800401E3))
        throw;
    oWord = new Microsoft.Office.Interop.Word.Application();
}
oWord.ScreenUpdating = false;
  

Это позволяет избежать необходимости инициализировать переменную null и позже проверять, все ли она еще существует null .

Более того, он явно обрабатывает условие ошибки, которое ваш код не может обработать. А именно ошибка COM, отличная от MK_E_UNAVAILABLE .

Комментарии:

1. @DavidHefferman: Спасибо за такой полностью информативный и полезный ответ… Я только что кое-что узнал!

Ответ №3:

Просто присвоите ей null значение по умолчанию:

 Microsoft.Office.Interop.Word._Application oWord = null;
  

Это необходимо, потому что в настоящее время код присваивает ей значение в if statement блоке catch {} , поэтому возможно, что oWord никогда не получит значение без начального / значения по умолчанию.

Комментарии:

1. Я не думаю, что области здесь уместны. Проблема просто в том, что локальная переменная не может быть назначена.

2. я меняю свой ответ, чтобы обозначить if оператор.

3. На мой взгляд, вам, как и @Anna, не хватает какой-либо обработки ошибок COM, кроме MK_E_UNAVAILABLE . Инициализация null просто выдает ошибку времени компиляции за ошибку времени выполнения.

4. Я не согласен. В этом суть вопроса. Именно поэтому переменная не инициализируется из-за того, что это условие не обрабатывается.

5. Нет. Вы вообще не понимаете. Переменная может по-прежнему иметь значение null после завершения catch, а затем вы обменяли ошибку времени компиляции на ошибку времени выполнения. Вам нужно устранить основную причину, по которой компилятор правильно жаловался.