Como resolver colisão de nomes de tipos [Dica Rápida .Net]

Há alguns dias, mexendo em um código legado, tive que incluir uma nova feature e, para isso, precisei adicionar uma referência a outro assembly, vamos chamar de “A”, no assembly (csproj) em que eu estava trabalhando.

Feito isso, o código deixou de compilar! Motivo: o código fazia uso de uma classe que possuía exatamente o mesmo nome de outra classe contida no assembly “A”. Sim, nome e o namespace completo iguaizinhos. :/

Como alterar o nome de uma delas era simplesmente inviável naquele momento, procurei alguma solução que pudesse desambiguar os nomes e descobri algo extremamente simples neste artigo aqui, de 2006!

(Como o artigo é muito antigo e o blog parece estar abandonado desde aquela época, vou descrever aqui a solução, caso aquele blog saia do ar.)

1. Crie uma nova Solution e adicione dois projetos novos, ambos do tipo Class Library, chamados FooVersion1 e FooVersion2.

2. No projeto FooVersion1, adicione a classe abaixo:

namespace Acme
{
   public class Foo
   {
      public void Bar() => Console.WriteLine("Bar");
   }
}

3. No projeto FooVersion2, adicione a classe abaixo (veja que tanto o namespace quanto o nome dela são iguais à da classe anterior):

namespace Acme
{
   public class Foo
   {
      public void Bar() => Console.WriteLine("Bar");
      public void Goo() => Console.WriteLine("Goo");
   }
}

4. Agora, para reproduzir o erro, adicione mais um projeto na Solution, dessa vez do tipo Console App, e chame-o de Consumer.

5. Adicione no Consumer, referências para os dois outros projetos, FooVersion1 e FooVersion2 (right-click em “References” ou “Dependencies” -> “Add Reference…”).

6. Ainda no Consumer, no método Main da classe Program (gerada automaticamente por ter criado um Console App), adicione o seguinte código e compile a aplicação:

var foo = new Acme.Foo();

7. Com isso, veremos o erro de compilação mais ou menos como abaixo:

“The type ‘Acme.Foo’ exists in both ‘FooVersion1…’ and ‘FooVersion2…'”

8. Para compilar, é preciso resolver a ambiguidade, o que é feito usando aliases para os assemblies referenciados. Vamos fazer isso para o FooVersion1. No projeto Consumer, ache a dependência FooVersion1 e entre em “Properties”:

doknow

Na janela que abrir, altere a propriedade “Aliases” para “LibFooVersion1”:

doknow2

obs.: exemplo usando projetos .Net Core com VS 2017 (as opções são ligeiramente diferentes em um projeto .Net full).

9. Basta compilar novamente o Consumer e você verá que o erro foi embora, porque agora o compilador entende que a classe Foo usada é a classe vinda de FooVersion2, que é a dependência onde não foi definido nenhum alias específico.

10. “E se eu quiser usar a outra classe?” Também é muito simples: basta fazer uso do alias definido no item 8. Primeiro, no topo do arquivo Program.cs do Consumer, coloque a seguinte diretiva (deve ser a primeira instrução dentro do arquivo):

extern alias LibFooVersion1;

11. E agora, altere o método Main para:

var f1 = new LibFooVersion1::Acme.Foo();
f1.Bar();

var f2 = new Acme.Foo();
f2.Bar();
f2.Goo();

12. Pronto! Agora é possível usar ambos os tipos, sem qualquer conflito. O próprio IntelliSense indicará os métodos corretos, de acordo com o tipo criado.

Obs.: você também poderia ter colocado um alias para o projeto FooVersion2, porém, recomendo deixar sem alias o tipo que aparece mais vezes no código, deixando-o mais limpo e sem necessidade de repetir em vários arquivos o uso da diretiva “extern alias”.

IMPORTANTE!
Use esta solução com parcimônia. Evite ao máximo a colisão de nomes, dando nomes bem explícitos e objetivos às suas classes e namespaces. Assim, além de evitar o problema descrito aqui, tanto para você quanto para qualquer outro consumidor da sua DLL, você também deixará o código mais fácil de ser entendido.

Era isso!

2 comentários em “Como resolver colisão de nomes de tipos [Dica Rápida .Net]

Adicione o seu

Deixar mensagem para Carlos Schults Cancelar resposta

Blog no WordPress.com.

Acima ↑