Вы находитесь на странице: 1из 12

Aplica-se a:

• ADO.NET

• .NET Language Integrated Query (LINQ)

• SQL Server
Resumo: Eliminar a diferença de impedância entre aplicações e serviços de dados como emissão de
relatórios, análise e replicação oferecidos como parte do produto SQL Server aumentando a abstração
do nível lógico (relacional) para o nível conceitual (entidade).

As pessoas que apenas utilizam o software não reconhecem a dificuldade que é escrevê-lo. O design
e o desenvolvimento são as partes divertidas. A parte difícil é fazer com que ele seja executado
corretamente (e com a rapidez necessária). Para o programador é como se uma refeição começasse
com um delicioso cheesecake duplo de café com creme e terminasse com creme de espinafre.
O motivo pelo qual dizemos que a programação é uma arte, e não uma ciência ou disciplina da
engenharia, é porque ainda não conseguimos dividi-la em suas etapas constituintes e mecanizá-la.
Após fazermos isso com êxito, uma nova escala de possibilidades surge: programas que escrevem
programas de linguagens de projeto orientadas a pessoas (PODL), programas para provar a correção
do programa e para analisar e suportar a consulta semântica. Até esse ponto, porém, a programação
continua sendo uma arte ou pelo menos é isso o que a sabedoria convencional diz.
Mas assim como acontece com grande parte da sabedoria convencional, essa analogia não resiste a
um exame mais detalhado. A criação de um programa (e já fazemos isso há mais de 20 anos) não é,
na verdade, nada parecido com arte – pelo menos não a arte de escrever ficção (e também já
fazemos isso há mais de 20 anos). Vou ilustrar essa questão com estes dois fragmentos de programa
e prosa.
Este primeiro exemplo é parte de um analisador léxico para analisar o Visual C++® 7.1. Ele é assim:
i f ( i ndex >= Token ID : : l as tKeyword ( ) ) {

s t r i ng token = tokenS t r ing ( i ndex ) ;

i f ( ( i sd ig i t ( token [ 0 ] ) ) | | ( token [0 ] == ‘ - ’ ) ) {

#i fde f TELL_ME

d i sp lay ( " ! ! TokenSe t : : token Ident i f y : " ,

"a l i t e ra l d ig i t : " , token ) ;

#end i f

re tu rn Token ID : :TK_L i te ra l ;

Este segundo exemplo é a abertura de um conto que escrevi há cerca de 27 anos, quando morava em
Tucson, no Arizona, lecionava e escrevia prosa:
We were her pride of 10, Miss Steward named us: the Prodigal, Phoenix,

Benjamin, and perspicacious, pacific Suzanne. Hush, child. Benjamin, be


s t i l l , Miss Steward commanded h im gent
People
l y. are never just.

Ambos os exemplos tiveram uma criação intensiva, ou seja, eu passei muito tempo antes criando a
arquitetura geral do trabalho, e os fragmentos refletem esse esforço de criação. O programa tem uma
falha de desempenho – eu recupero a entrada de cadeia de caracteres na tabela de cadeia de
caracteres associada por valor e não por ponteiro. Se o código precisasse ser produzido, ele exigiria
uma revisão óbvia. Isso não tem nada a ver com a correção, mas apenas com o desempenho. Para
um programa com código fonte pequeno, a diferença de velocidade não é mensurável e, assim, eu
preferi a sintaxe de objeto mais limpa e lenta, uma vez que não gosto dos tokens de manipulação de
ponteiros da C/C++.
Embora minha prosa não tenha atraído milhões de leitores, aqueles que a leram apreciaram a obra
com sua trama emocional sob uma rigorosa estrutura simbólica. Aqueles que não apreciam a prosa
tradicional acharam que ela era enganosa, porque não há nada de funcional nela. A finalidade da arte
é projetar sentimentos e a realidade de uma vida privada subjetiva em meio aos eventos públicos em
um meio plástico em particular – no caso da prosa, as palavras. Obviamente, não há valor nisso, não
como o valor intrínseco de um programa.
Eu gosto do processo de criação de um programa, e gosto de experimentar o modo como as
diferentes partes interagem. Eu gosto de definir abstrações ou famílias de abstrações. Eu as considero
meu elenco de personagens. Gosto também de criar interfaces, porque representam as coisas que
meus personagens fazem. E é assim como eu realmente escrevo os programas.
Eu não gosto de escrever expressões e declarações. Eu gostaria que tivéssemos uma linguagem de
programação simbólica na qual eu pensasse melhor e que pudesse memorizar. Honestamente, eu não
consigo manter a clareza de expressões e aninhamentos intercalados. Embora eu consiga manter oito
seções separadas de texto em minha cabeça e as compare e as ecoe, eu não consigo dar sentido a um
programa além das classes que crio e suas interfaces.
No excelente artigo de John Markoff sobre a indústria do PC, What the Dormouse Said, ele declara que
o objetivo dos visionários iniciais - colocar um computador à disposição de cada pessoa - foi
concretizado. Mas ele está errado. Esse objetivo foi concretizado apenas pela metade. O que há de
bom em todo esse poder da computação se uma pessoa não pode programá-la? Ainda não realizamos
seu sonho porque ainda não descobrimos como tornar a programação uma arte para que todos
possam compartilhá-la. Até lá, a programação continua não sendo uma disciplina da ciência, nem um
domínio da arte. Por enquanto, a programação é pouco mais do que uma nova alquimia. Ninguém
realmente a entende e ninguém ainda transformou uma especificação em ouro verdadeiro.
Stanley B. Lippman começou a trabalhar na linguagem C++ junto com seu criador, Bjarne
Stroustrup, em1984, na Bell Laboratories. Mais tarde, Stan trabalhou em animação de filmes na
Disney e na DreamWorks e atuou como diretor técnico de software no filme Fantasia 2000. Desde
então, tem trabalhado como consultor condecorado da JPL e arquiteto na equipe do Visual C++ da
Microsoft.
P Quando gero uma DLL com suporte de automação usando o Visual C++® 6.0, são geradas algumas
funções de registro, mas não para cancelar o registro da minha DLL. Escrevi um DllUnregisterServer
que tem esta aparência:
STDAPI DllUnregisterServer(void)

AFX_MANAGE_STATE(AfxGetStaticModuleState());
i f ( !CO leOb jec t Fac to r y : :Un reg i s te rA l l ( ) )

re tu rn Resu l t FromScode(SELFREG_E_CLASS) ;

return NOERROR;

COleObjectFactory::UnregisterAll retorna TRUE, mas minha DLL ainda está registrada. Como devo
escrever o código?
Ivan Pavlik
R Bem, você esbarrou em uma pequena fenda especial no universo MFC. UnregisterAll parece mesmo
ser a função a ser chamada para cancelar o registro de sua DLL. Se olhar no olefact.cpp, onde o
UnregisterAll é implementado, você verá que é mais ou menos assim:
for (/* pFactory = all factories */) {

pFactory->Unregister();

Isto é, ele faz um loop sobre todas as fábricas de seu módulo e chama o Unregister para cada uma
delas. Até aqui, tudo bem. O que o COleObjectFactory::Unregister faz? O código revela a história:
BOOL COleObjectFactory::Unregister()

return TRUE;

Opa! Como você pode ver, o COleObjectFactory::Unregister não faz nada! Ele simplesmente retorna
TRUE. Isso é muito peculiar, pois o COleObjectFactory::Register registra realmente sua classe COM
chamando ::CoRegisterClassObject. Por outro lado, há uma outra função, COleObjectFactory::Revoke,
que chama ::CoRevokeClassObject para cancelar o registro de sua classe COM. MFC chama Revoke
automaticamente a partir de seu destruidor de COleObjectFactory. Então, o que é que está
acontecendo aqui?
O problema é uma confusão infeliz na terminologia, que tem origem nos diferentes modos de registrar
as classes COM para DLLs e EXEs. Para DLLs, você registra sua classe adicionando chaves ao registro
do Windows (CLSID, ProgID e assim por diante). Para EXEs, você precisa chamar
CoRegisterClassObject para registrar sua classe no sistema COM no tempo de execução. A questão
fica ainda mais confusa pelo fato de que para os EXEs, o oposto de registrar não é cancelar o registro,
mas revogar (CoRevokeClassObject).
Quando as pessoas de Redmond adicionaram o suporte COM ao MFC, elas fizeram o que puderam para
facilitar ao máximo a vida das pessoas, mas nem sempre tiveram muito sucesso.
COleObjectFactory::Register tem esta aparência:
// in olefact.cpp

BOOL COleObjectFactory::Register()

if (!afxContextIsDLL) {
: :CoReg i s te rC lassOb jec t ( . . . ,

CLSCTX_LOCAL_SERVER , . . ) ;

Você pode ver de imediato que não faz nada para DLLs; ele só registra EXEs usando
CLSCTX_LOCAL_SERVER (contexto = servidor local, EXE em execução na máquina local). Seguindo a
C API básica, as pessoas de Redmond usaram o mesmo nome Revoke para a função que cancela o
registro do EXE: COleObjectFactory::Revoke (que é chamado automaticamente pelo seu destruidor de
fábrica de classes).
Então, para o que serve COleObjectFactory::Unregister a função que não faz nada? Talvez as pessoas
de Redmond pretendessem fazer com que um dia Register/Unregister funcionassem também para
DLLs. Mas, do jeito que está agora, não funcionam. Para registrar seu DLL, você precisa de uma outra
função completamente diferente: COleObjectFactory::UpdateRegistry. Essa função usa um argumento
booleano que diz ao MFC se você quer registrar ou cancelar o registro de sua classe COM. Há também
UpdateRegistryAll, que executa um loop sobre todas as fábricas de classes, chamando UpdateRegistry
para cada uma. Então, aqui está o modo adequado para implementar seu DllUnregisterServer::
STDAP I Dl lUnreg i s te rSe rve r (vo id )

AFX_MANAGE_STATE(AfxGe tS ta t i cModu leS ta te ( ) ) ;

re tu rn COleOb jec t Fac to r y : :UpdateReg i s t ryA l l ( FALSE)

? S_OK : SELFREG_E_CLASS ;

DllRegisterServer deve parecer igual, mas você deve passar TRUE em vez de FALSE para
UpdateRegistryAll.
A implementação padrão para UpdateRegistry faz o que pode para adicionar ou remover as chaves de
registro apropriadas em HKCR/CLSID–InprocServer32, ProgID, Insertable, ThreadingModel e assim
por diante, mas, às vezes, você precisará de outras chaves específicas para sua classe COM. Por
exemplo, pode ser preciso registrar categorias, que são um tipo de extensão da antiga chave
"Insertable" (o que significa que sua classe COM pode ser ignorada em uma forma no modo de
design). Nesse caso, você precisa ignorar o UpdateRegistry para adicionar ou remover suas próprias
chaves.
Há tempos, nos exemplares de novembro e dezembro de 1999 do Microsoft Systems Journal (agora
chamados de MSDN®Magazine), mostrei como construir um Band Object para Internet Explorer
usando a interface Active Template Library (ATL) IRegistrar. (Band Objects precisam ser registrados
como uma categoria especial CATID_DeskBand.) IRegistrar é uma ferramenta muito boa que permite
que você escreva um script de registro (arquivo .RGS) para adicionar suas entradas ao registro, em
vez de chamar funções de registro como RegOpenKey, RegSetValue e outras mais. A Figura 1 mostra
um script típico.
Como você pode ver, IRegistrar permite que você defina variáveis como %ClassName% e
%ThreadingModel% e depois as substitua com valores reais no tempo de execução. Com IRegistrar,
você nunca mais terá de chamar a API de registro. Você pode escrever um script que se pareça mais
com as entradas reais do registro e pode, inclusive, usar o mesmo script para registrar ou cancelar o
registro de sua DLL. Isso mesmo, o IRegistrar é inteligente o bastante para cancelar o registro. O
IRegistrar não está documentado oficialmente em lugar algum que eu pudesse encontrar, mas o
código está aqui (encontre-o em atliface.h). Se ainda não está usando o IRegistrar para registrar e
cancelar o registro de suas COM DLLs, você deveria mesmo experimentar — isso vai poupar-lhe muito
trabalho. Para obter detalhes consulte meu artigo no exemplar de novembro de 1999 .
P Meu aplicativo principal tem um menu normal com um submenu de comandos Editar (Recortar,
Copiar, Colar etc.). Gostaria de exibir o submenu Editar como um menu de contexto quando o usuário
clica com o botão direito na janela principal. O problema é como obter esse submenu a partir do menu
principal. Parece que não existe nenhuma ID de comando associada a um submenu. Posso usar o
índice começando em zero, mas devido à personalização o menu Editar nem sempre será o segundo
menu. Não posso procurar o texto "Editar" porque damos suporte a múltiplos idiomas e a palavra
verdadeira pode mudar. Como posso localizar o submenu Editar em todos esses casos?
Brian Manlin
R Bem, deixe-me salientar que o menu Editar deveria ser o segundo submenu, se você tiver um. As
diretrizes de GUI do Official Windows® necessitam que os três primeiros itens de menu sejam Arquivo,
Editar, Exibir, nessa ordem — para receberem suporte. Consulte Windows Interface Guidelines for
Software Design (em inglês) (Microsoft Press®, 1995). Dito isso, posso ajudá-lo a encontrar seu
submenu Editar ou qualquer outro submenu desejado.
Você está correto: não existe ID de comando para um submenu. Isso acontece porque internamente o
Windows usa o campo de ID de comando para armazenar o HMENU de submenu, se o item de menu é
um submenu. Não se preocupe, supondo que o submenu sempre mantenha um comando específico
(por exemplo Editar | Recortar) e supondo que o comando sempre tenha a mesma ID (por exemplo,
ID_EDIT_CUT), é bem fácil escrever uma função que localize o submenu que contém um determinado
comando. A Figura 2 mostra o código. CSubmenuFinder atua de fato como um namespace para
armazenar a função estática FindCommandID, que chama a si mesma recursivamente para uma busca
detalhada no menu e em todos os submenus por um item cuja ID de comando corresponda à procura.
Esse segmento busca no menu principal um submenu que contenha um item de menu cuja ID de
comando seja ID_EDIT_CUT e retorna o submenu, se localizado. Escrevi um pequeno programa
denominado EdMenu para testar o CSubmenuFinder. O EdMenu usa o código anterior para manipular
WM_CONTEXTMENU de modo a exibir um submenu editar exatamente igual ao do menu principal,
quando o usuário clica com o botão direito na janela principal. Acredite em mim quando digo que o
CSubmenuFinder localiza o menu editar onde quer que ele esteja dentro do menu principal. Na
verdade, eu o testei quando mudei temporariamente o menu Editar para adiante do menu Exibir em
uma de minhas criações. Experimente você mesmo, faça download da fonte.
P Como converto MFC CString em String em C++ gerenciado? Por exemplo, tenho o seguinte código
em C++:
vo id GetS t r ing (CS t r ing& msg)

msg = / / bu i ld a s t r ing

}
Como posso reescrever essa função usando C++ gerenciado e substituindo o parâmetro CString por
uma String gerenciada? O problema é que GetString muda a CString do chamador e eu quero fazer a
mesma coisa usando uma String gerenciada.
Sumit Prakash
R Bem, a resposta depende de você estar usando a nova sintaxe C++/CLI ou as antigas extensões
gerenciadas. Os dois tipos de sintaxe podem ser confusos, mas não tenha medo, estou aqui para
resolver sua confusão de códigos.
Vamos começar pela nova sintaxe, pois estamos em 2006. O truque para acertar a sintaxe é lembrar
de duas coisas. Primeiro, em C++/CLI, os objetos gerenciados usam chapéus. Assim, CString torna-se
String^. Segundo, lembre-se de que o equivalente gerenciado à referência (&) é a referência de
rastreamento, que em C++/CLI é %. Sei, você mal pode enfiar ^ em seu cérebro, mas, com alguma
prática, % também logo vai parecer normal. Então, as novas funções ficam assim:
/ / us ing C++/CL I

vo id GetS t r ing (S t r ing^% msg)

msg = / / bu i ld a s t r ing

Isso faz sentido? Para mostrar que funciona de fato, escrevi um pequeno programa strnet.cpp (veja a
Figura 3). Ele implementa duas classes, CFoo1 e CFoo2, cada uma com um membro GetName. A
primeira usa CString& e a segunda usa String^%. Se você compilar e executar esse programa
(usando /clr é claro), verá que nos dois casos — o que usa CString e o que usa String — o objeto
passado (nativo ou gerenciado) é modificado pela função de membro.
Por falar nisso, sempre use uma referência de rastreamento (%) para objetos gerenciados, em vez de
usar uma referência nativa (&, que também fará compilação) porque a referência de rastreamento
rastreará a referência mesmo se o coletor de lixo mover o objeto dentro de sua pilha gerenciada.
Se você está usando a sintaxe no estilo antigo (/clr:oldSyntax), como pode ainda viver na Idade
Média? Nada tema, você pode usar uma referência mesmo que seja antiga. Se você está usando
extensões gerenciadas, lembre-se apenas de que os objetos gerenciados são __gc pointers e assim
CString transforma-se em String __gc *. E, como o compilador já sabe que String é um tipo
gerenciado, você nem vai precisar do __gc; um ponteiro simples (*) bastará. A referência é a mesma.
Então, a conversão da sintaxe de estilo antigo fica assim:
/ / __gc omi t ted

vo id GetS t r ing (S t r ing*& msg)

msg = / / bu i ld a s t r ing

Entendeu? Faz todo o sentido. Sempre que tiver dificuldade em descobrir a sintaxe C++, a solução
será voltar ao básico.
P Recentemente gerei um aplicativo de console CLR com o Visual Studio® 2005. Reparei que o Visual
Studio criou uma função principal como esta:
i n t main (a r ray<Sys tem: :S t r ing ^> ^args )

...

re tu rn 0 ;

Isso parece ser uma mudança da antiga argc/argv com que estou familiarizado no C/C++. Quando
tentei acessar args[0], pensando que seria o nome do arquivo (como em C/C++), descobri que
args[0] não é o nome do arquivo, mas o primeiro parâmetro da linha de comando. O que aconteceu
com o nome do arquivo? Pode me explicar a razão desta mudança?
Jason Landrew
R Ah, o mundo moderno em que nos divertimos! Nada é igual ao que era, não é verdade? Vivemos
com argc/argv desde que a linguagem C foi desenvolvida em 1972 e agora as pessoas de Redmond
vieram e mudaram tudo. Talvez eles quisessem ter certeza de que todos saberiam como usar a nova
matriz de sintaxe.
Uma razão para a nova sintaxe é gerar um programa que compile com /clr:safe, que é a última
palavra em segurança de código. É como trancar seu programa dentro de uma sala limpa — um
daqueles ambientes estéreis cheios de equipamentos de cromo, em que é preciso entrar através de
uma câmara de vácuo de pressão negativa, usando capacete e botas especiais. Quando você aciona o
comutador /clr:safe, o compilador impõe todos os tipos de restrições trabalhosas. Não é possível usar
tipos nativos. Não é possível usar globais. Você não pode chamar funções não gerenciadas. Em
resumo, você não pode fazer nada divertido. E por que você se sujeitaria a tanto sofrimento? Para ter
certeza total e absoluta de que o código está seguro. Em termos técnicos, /clr:safe gera código
"verificável", o que significa que o CLR (Common Language Runtime) pode verificar que seu código
não viola configurações de segurança, tais como tentar acessar um arquivo quando as configurações
de segurança do usuário não permitem. Um dos muitos itens da lista proibida do /clr:safe é ponteiros
nativos — ou seja, ponteiros. ("Nativo" é redundante, pois não se pode ter um ponteiro de tipo
gerenciado.) Como os ponteiros não são permitidos com o /clr:safe, a antiga declaração argv
simplesmente não funciona. Assim, as pessoas de Redmond mudaram a declaração para usar uma
matriz String^. E como as matrizes conhecem seu comprimento, não há necessidade de argc. A
biblioteca de tempo de execução proporciona o código de inicialização apropriado para criar e
inicializar a matriz de arg antes de chamar sua função principal. Se você não planeja usar /clr:safe,
sempre é possível escrever um principal que use a antiga assinatura argc/argv .
Isso explica o motivo de se usar uma matriz gerenciada, mas e o args[0], por que ele é o parâmetro
do primeiro comando e não o nome do arquivo? Não posso falar pelas pessoas de Redmond, mas
talvez tenham achado que faria mais sentido omitir o nome do arquivo, talvez pensassem que você
não precisaria disso. De qualquer modo, não importa muito porque é fácil obter o nome do arquivo.
Tenho certeza de que existem muitos modos de fazer isso, mas o mais óbvio e centrado em CLR
(compatível com /clr:safe) em que posso pensar é usar a classe de System::Environment. Ela
apresenta o seguinte método:
s ta t i c ar ray<St r ing^>^ GetCommandL ineArgs ( )

Ao contrário do parâmetro args fornecido para o método principal, a matriz retornada por
Environment::GetCommandLineArgs na verdade começa com o nome do arquivo executável.
Finalmente, por que você desejaria saber o nome de seu próprio arquivo EXE? Afinal de contas, se
você está escrevendo o programa, supostamente sabe como ele se chama. Um motivo seria gerar
uma mensagem de ajuda que contenha o nome do programa, sem codificá-lo. A mensagem de ajuda
poderia ser mais ou menos assim:
FooF i l e - - Tu rns every word i n your f i l e to " foo "

usage :

FooF i l e [ /n :<number>] f i l e spec

f i l e spec = the f i l e s you want to change

<number> = change on ly the f i r s t <number> occu r rences

Aqui, FooFile é o nome do programa. Eu poderia simplesmente escrever "FooFile" em meu texto de
ajuda, mas aprendi há muito tempo que muitas vezes renomeio programas ou copio códigos de um
programa para outro. Obtendo o nome do programa a partir do próprio programa (por meio de argv
ou Environment::GetCommandLineArgs), minhas mensagens de ajuda sempre exibem o nome
correto, mesmo que eu renomeie o arquivo ou copie meu código em outro programa.
Boa programação!
Envie perguntas e comentários para Paul no endereço: cppqa@microsoft.com.
Paul DiLascia é um consultor de software independente e um designer de interfaces de usuário e
aplicativos Web. Ele é o autor de Windows++: Writing Reusable Windows Code in C++ (Addison-
Wesley, 1992). Em seu tempo livre, Paul desenvolve a PixieLib, uma biblioteca de classes do MFC
disponível em seu site, http://www.dilascia.com/.

C++ foi a linguagem contemplada com a maior quantidade de modificações no Visual Studio
.NET 2003, a próxima versão do Visual Studio .NET.

As linguagens mais recomendadas para o desenvolvimento na plataforma .NET são sem dúvida o
Visual Basic e o C#. Isto fica claro ao se constatar que tanto a documentação como os exemplos são
sempre fornecidos nas das linguagens e, em muitos casos, apenas elas. Efetivamente, o C# e o VB
são produtivos e fáceis de aprender e usar.

Como fica então o C++? O C++ passa a ser oficialmente considerada uma linguagem mais de "baixo
nível" - se é que você já não achava isto antes. Dentro desta filosofia, o C++ do Visual Studio .NET
possui alguns um recurso único: É a única linguagem capaz de gerar código "não-gerenciado", ou
seja, código Win32 como era desenvolvido antes da plataforma .NET. Isto continua sendo necessário,
notavelmente na criação de "device-drivers". Além dito, é possível criar executáveis contendo código
gerenciado e não-gerenciado, algo interessante na criação de programas que devem interagir com os
dois mundos, como as próprias ferramentas de desenvolvimento.

O Visual Studio 2003 traz algumas novidades a mais na linguagem C++: agora é possível criar
aplicativos RAD e também gerar "código verificável".

Aplicativos RAD

O paradigma de programação RAD foi introduzido pelo Visual Basic em 1991 e amplamente copiado
por várias outras ferramentas de desenvolvimento. Neste paradigma, colocamos "componentes" sobre
formulários, ajustamos propriedades dos componentes e interceptamos eventos dos componentes em
nosso código. Infelizmente o Visual Studio .NET original não trazia suporte a desenvolvimento RAD na
linguagem C++.

Com o Visual Studio .NET 2003 é possível criar aplicativos "RAD" em C++. Podemos criar tanto
"Windows Forms Applications" como "Windows Control Libraries":

Veja a janela principal do projeto C++. Observe que podemos alterar propriedades na janela da
direita:
Observe que os componentes possuem diversos eventos, como no caso do Button1 mostrado a seguir:
Os eventos mostrados acima são eventos dos próprios componentes da biblioteca .NET Framework.
Veja o código para processar o evento Click do botão:

Código Verificável

Todo programa criado pelo compilador VB.NET e também a maioria dos programas criados pelo
compilador C# é dito "verificável". Isto quer dizer que o compilador JIT pode, em tempo de
execução/compilação verificar e garantir que o programa não faça nenhuma operação que possa
comprometer a segurança e integridade do sistema.

Pode parecer estranho, mas existem instruções MSIL capazes de abrir brechas na segurança do
sistema, como por exemplo, para manuseio direto de ponteiros ou manuseio da pilha da CPU. Estas
instruções são necessárias em alguns casos, como por exemplo para que a própria biblioteca chame a
API do Windows. Programas que contem estas instruções são ditos "não-verificáveis". Evidentemente
é necessário um privilégio especial de segurança para rodar programas não-verificáveis.

O compilador C++ do Visual Studio 2002 sempre gera código não-verificável, o que é sem dúvida uma
deficiência. Já o Visual Studio 2003 pode gerar código verificável, desde que se façam alguns ajustes
de compilação.

Criar código verificável exige uma seqüência de ajustes, documentada sob o tópico "Producing
Verifiable Components with Managed Extensions for C++":
Conclusão

O C++ foi significativamente melhorado no Visual Studio .NET 2003 e com certeza agradará os seus
entusiastas, tanto com relação ao uso de recursos RAD como à criação de código verificável.