VS 2008中即时窗口的奇特行为

时间:2010-10-05 12:38:15

标签: visual-studio-2008 debugging immediate-window

今天在VS 2008中进行调试时发生了一些奇怪的事情。我将给出小代码片段

List<IPageHandler> myPageList = TaskSOM.PageList;

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

在运行应用程序时,类型转换失败并且aPage变为null(这是调试的原因)。所以使用该变量的所有代码都失败了。但是在调试期间,myPageList中的第一个元素是一个PageHandler。当我在即时窗口中执行该行

  PageHandler aPage = myPageList[0] as PageHandler;

aPage变量具有适当的值。但是如果将调试器移动到该行并执行我得到一个null。由于机密性,我无法分享整个代码。但是,过去有任何人都遇到了这个问题。是否存在关于即时窗口如何工作的任何材料。

2 个答案:

答案 0 :(得分:1)

这是一个非常好的代码示例,其中想要将用作运算符。很明显,你无法承受演员阵容的失败,或者如果演员阵容失败,你会包括一个空测试并做一些有意义的事情。

使用真正的演员。您将获得一个信息丰富的异常,为您提供更好的提示,为什么演员会失败:

 PageHandler aPage = (PageHandler)myPageList[0];

例外是你的朋友,不要避开它们。猜测一下:当您在线程中使用COM对象并且COM服务器不支持封送时,可能会发生这种情况。如果是这种情况,则异常消息将告诉您。

答案 1 :(得分:0)

所以这是完整的细节。例外是

[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 so应用程序的一部分从[A]创建了PageHandler实例并填充了列表,另一部分试图从[B]中输入强制转换为PageHandler。

以下示例将轻松触发此错误。希望这有助于某人。 这是一个简单的类库。将其构建为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();
            }
      }
}