【问题标题】:Peculiar behavior of immediate window in VS 2008VS 2008 中即时窗口的特殊行为
【发布时间】:2010-10-05 12:38:14
【问题描述】:

今天在VS 2008调试的时候发生了一件奇怪的事情,我给小代码sn-p

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 变量具有适当的值。但是如果将调试器移到该行并执行,我会得到一个空值。由于保密,我无法分享整个代码。但是过去有没有人在直接窗口中遇到过这样的问题。有没有关于即时窗口如何工作的资料。

【问题讨论】:

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


    【解决方案1】:

    这将是您想使用as操作符的一个很好的代码示例。显然,您不能承受强制转换失败的代价,否则如果强制转换失败,您将包含一个空测试并做一些有意义的事情。

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

     PageHandler aPage = (PageHandler)myPageList[0];
    

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

    【讨论】:

    • 感谢您的快速回复。我发现了问题。我将添加另一篇文章以提供完整的详细信息。
    • 我已经给出了这个问题的答案。但我仍然不明白相同类型的演员如何在即时窗口中工作。
    • Assembly.LoadFile() 应该永远在您编写特殊的程序集转储工具时使用。使用 LoadFrom()。
    【解决方案2】:

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

    [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 构建了真正的应用程序,所以应用程序的一部分从 [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();
                }
          }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      • 2012-03-18
      • 1970-01-01
      • 2021-03-29
      • 1970-01-01
      相关资源
      最近更新 更多