Своеобразное поведение непосредственного окна в VS 2008 - PullRequest
0 голосов
/ 05 октября 2010

Сегодня при отладке в VS 2008 произошло нечто странное. Я приведу небольшой фрагмент кода

List<IPageHandler> myPageList = TaskSOM.PageList;

if( myPageList != null && myPageList.Count > 0 )
{
     PageHandler aPage = myPageList[0] as PageHandler;
     ...; // Some more code below  
}

Во время работы приложения произошел сбой при типизации, и aPage стал нулевым (это было причиной отладки) Таким образом, весь код, который использовал эту переменную, потерпел неудачу. Но во время отладки первым элементом myPageList был PageHandler. Когда я выполняю строку в ближайшем окне

  PageHandler aPage = myPageList[0] as PageHandler;

Переменная aPage имеет правильное значение. Но если переместить отладчик в эту строку и выполнить, я получаю ноль. Из-за конфиденциальности я не мог поделиться всем кодом. Но кто-нибудь сталкивался с такой проблемой с непосредственным окном в прошлом. Есть ли какие-либо материалы о том, как работает непосредственное окно.

Ответы [ 2 ]

1 голос
/ 05 октября 2010

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

Используйте настоящий актерский состав. Вы получите информативное исключение, которое даст вам гораздо лучший совет о том, почему не удалось выполнить приведение:

 PageHandler aPage = (PageHandler)myPageList[0];

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

0 голосов
/ 06 октября 2010

Итак, вот полная информация.Исключение составляло

[A]SimpleClassLib.PageHandler cannot be cast to [B]SimpleClassLib.PageHandler. Type A originates from 'SimpleClassLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadNeither' at location 'D:...\bin\SimpleClassLib.dll'. Type B originates from 'SimpleClassLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'D:...\bin\Debug\SimpleClassLib.dll'

Разработчик упомянул [A] D: ... \ bin \ SimpleClassLib.dll в одном из файлов конфигурации приложения и создал реальное приложение с помощью [B] D: ... \ bin \ Debug \ SimpleClassLib.dll, поэтому одна часть приложения создала экземпляр PageHandler из [A] и заполнила список, а другая часть пыталась набрать приведение к PageHandler из [B].

Следующий пример легко вызовет эту ошибку.Надеюсь, это кому-нибудь поможет.Это простая библиотека классов.Постройте это как dll.

// SimpleClassLib.dll    
namespace SimpleClassLib
    {
        public class Foo
        {
            string Prop1 { get { return "I am Foo!!"; } }
        }
    }

Ниже приведено консольное приложение.Приложение ссылается на SimpleClassLib как обычная ссылка добавления из VS 2008. Также оно загружает экземпляр по другому пути.

// Separate console application App.exe
// Progoram.cs
using SimpleClassLib;
namespace App
{
  class Program
  {
            List<object> myFooList;
            Program()
            {
                myFooList = new List<object>();
                Assembly a = Assembly.LoadFile(@"<differentpath>\SimpleClassLib.dll");
                Type aFooType = a.GetType("SimpleClassLib.Foo");
                ConstructorInfo aConstructor = aFooType.GetConstructor(new Type[] { });
                myFooList.Add(aConstructor.Invoke(new object[]{}));
                myFooList.Add(aConstructor.Invoke(new object[] { }));
                myFooList.Add(aConstructor.Invoke(new object[] { }));
            }

            void DumpPeculiar()
            {
                for (int i = 0; i < myFooList.Count; i++)
                {
                    // If one inspects the list in debugger will see a list of
                    // Foo but this Foo comes from a different load context so the
                    // following cast will fail. While if one executes the line
                    //  f = myFooList[i] as Foo
                    // it will succeed
                    Foo f = myFooList[i] as Foo;
                    Foo f1 = (Foo)myFooList[i];
                }
            }

            static void Main(string[] args)
            {
                Program p = new Program();
                p.DumpPeculiar();
            }
      }
}
...