Option Strict e ByRef

Todo mundo já sabe que o VB.NET não é uma linguagem fortemente tipada (strongly typed) tal como C, C++ ou C#. Mas o que é uma linguagem fortemente tipada? Ser fortemente tipada indica que cada variável possui um tipo definido em tempo de compilação.

Em VB.NET podemos realizar conversões de dois tipos: widening e narrowing. Para exemplificar melhor digamos que temos as duas variáveis abaixo.

Dim var1 As System.Int32
Dim var2 As System.Int16

A conversão widening muda o valor de um tipo que pode acomodar qualquer possível valor do tipo original. Por exemplo, o tipo System.Int32 contém toda a faixa de valores do tipo System.Int16.

' conversão widening
var1 = var2

A conversão narrowing muda o valor de um tipo que pode não estar apto a armazenar alguns possíveis valores do tipo original. Por exemplo, o tipo System.Int16 contém uma parte dos valores do tipo System.Int32.

' conversão narrowing
var2 = var1

Em VB.NET existe uma opção chamada Option Strict que, quando ligada, restringe conversões implícitas de tipos para somente conversões do tipo widening. O uso dessa opção é extremamente recomendada, já que temos as seguintes vantagens:

  • Checagem do tipo em tempo de compilação (strong typing).
  • Previne perda de dados em conversões.
  • Não permite late-binding, ou seja, não permite que as conversões sejam checadas em tempo de execução.
  • Melhora a performance porque o tipo é explícito e de certa forma não precisa ser “adivinhado”.

O engraçado dessa história é que a opção vem desabilitada por padrão. É possível habilitá-la pelo código, pela IDE do Visual Studio ou alterando uma opção pelo compilador.

Para habilitar a opção pelo código temos que incluir o seguinte trecho no início do código-fonte antes de qualquer outro código.

Option Strict On

Para definir a opção pela IDE do Visual Studio temos que seguir os seguintes passos.

  1. No menu Tools, clique em Options.
  2. Vá até o nó Projects and Solutions.
  3. Escolha VBDefaults.
  4. Modifique a configuração do Option Strict.

Para definir no compilador a opção /optionstrict deve ser adicionada à linha de comando.

Bom, vamos chegamos agora ao ponto principal do post que é mostrar o comportamento dessa opção em um caso específico. Digamos que temos o seguinte método abaixo:

Public Sub MetodoX(ByRef obj As Object)
...
End Sub 

Considerando que qualquer tipo no .NET herda de System.Object podemos passar então qualquer tipo de variável para esse método. Correto?

NÃO se a opção Option Strict estiver ligada. Por quê?

Quando passamos o um argumento ByRef para um método este pode alterar o valor do parâmetro. Como o parâmetro do exemplo é um tipo System.Object, dentro do método a variável obj pode ser convertida para qualquer outro tipo, inclusive um tipo cuja conversão seja do tipo narrowing.

Explicando melhor, se passarmos por exemplo um valor do tipo System.Int32 para o método e dentro deste a variável obj é convertida para System.Int64, como o parâmetro é ByRef, uma conversão narrowing será realizada (tentativa de transformar System.Int32 em System.Int64). O código gera o seguinte erro: Option Strict On disallows implicit conversions.

Dim param1 As System.Int16

' chamada do método
MetodoX(param1)

' quem garante que após a chamada do método o parâmetro continua sendo System.Int16?

Se parâmetro obj do método for modificado para ByVal, o erro desaparece porque não temos mais a conversão narrowing.

Esse foi uma questão interessante de um colega dos fóruns do MSDN.

Links de ajuda:

Option Strict Statement
http://bit.ly/8Fl9oj

Option Strict On disallows narrowing from type '' to type '' in copying the value of ByRef parameter ' back to the matching argument
http://bit.ly/6V4Bf8

Widening and Narrowing Conversions
http://bit.ly/8GiNBW

Nenhum comentário:

Postar um comentário