0

今日、VS2008でのデバッグ中に何か奇妙なことが起こりました。小さなコードスニペットを提供します

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が発生します。機密保持のため、コード全体を共有できませんでした。しかし、過去に当面のウィンドウでそのような問題に直面した人はいますか。即時ウィンドウがどのように機能するかに関する資料はありますか。

4

2 に答える 2

1

これは、 as演算子を使用したくないコードの非常に良い例です。明らかに、キャストを失敗させる余裕はありません。そうでない場合は、nullテストを含めて、キャストが失敗した場合に意味のあることを実行します。

本物のキャストを使用してください。キャストが失敗した理由のより良いヒントを与える有益な例外が表示されます。

 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'

開発者は、アプリケーション構成ファイルの1つで[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!!"; } }
        }
    }

以下はコンソールアプリです。アプリは、VS 2008からの通常の追加参照のように、SimpleClassLibにリンクします。また、別のパスからインスタンスをロードします。

// 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 に答える