Comportamento peculiar da janela imediata em vs 2008
-
27-09-2019 - |
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.
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();
}
}
}