0

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

4

2 回答 2

1

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

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

 PageHandler aPage = (PageHandler)myPageList[0];

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

于 2010-10-05T13:34:01.583 回答
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 构建了真正的应用程序,因此是其中的一部分应用程序从 [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();
            }
      }
}
于 2010-10-06T11:46:03.697 回答