Pergunta

Hoje, algo peculiar aconteceu enquanto depura no VS 2008. Vou dar o pequeno trecho de código

List<IPageHandler> myPageList = TaskSOM.PageList;

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

Enquanto executa o aplicativo, o TypeCast falhou e o APage se tornou nulo (esse foi o motivo da depuração). Portanto, todo o código que estava usando esse vaable falhou. Mas durante a depuração, o primeiro elemento no MyPagelist foi atingido por um manipulador de página. Quando eu executo a linha na janela imediata

  PageHandler aPage = myPageList[0] as PageHandler;

A variável APage tem valor adequado. Mas se mover o depurador para essa linha e executar, eu recebo um nulo. Devido à confidencialidade, não pude compartilhar todo o código. Mas alguém enfrentou um problema com a janela imediata no passado. Existe algum material sobre como a janela imediata funciona.

Foi útil?

Solução

Este seria um exemplo muito bom de código onde você não quer usar o Como operador. Claramente, você não pode pagar o elenco para falhar ou teria incluído um teste nulo e fez algo significativo se o elenco falhasse.

Use um elenco real. Você terá uma exceção informativa que lhe dá uma dica muito melhor por que o elenco falhou:

 PageHandler aPage = (PageHandler)myPageList[0];

Exceções são seu amigo, não evite -as. Tomando um palpite selvagem: isso pode acontecer quando você usa um objeto COM em um thread e o servidor COM não suporta o marechaling. Se for esse o caso, a mensagem de exceção dirá isso.

Outras dicas

Então, aqui estão os detalhes completos. A exceção foi

[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'

O desenvolvedor mencionou [a] d: ... bin simpleclasslib.dll em um dos arquivos de configuração do aplicativo e construiu o aplicativo real com [b] d: ... bin debug simpleclasslib.dll, então uma parte de O aplicativo criou a instância PageHandler de [A] e preencheu a lista e a outra parte estava tentando digitar o Cast para PageHandler de [B].

O exemplo a seguir acionará esse erro facilmente. Espero que isso ajude alguém. Esta é a biblioteca de classes simples. Construa isso como uma DLL.

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

A seguir, o aplicativo console. O aplicativo links para o simpleclasslib como o normal Adicionar referência do VS 2008. Além disso, ele carrega uma instância de outro caminho.

// 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();
            }
      }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top