Pergunta

Eu tenho um projeto onde eu quero ter verificado aritmética por padrão, com exceção de ponto sensível uma performance. Infelizmente, VB.Net não tem um bloco 'desmarcada'.

Idealmente, o quadro teria algum tipo de tipo inteiro com a aritmética explicitamente desmarcada, mas eu não encontrei nada parecido. Eu achar que árvores de expressão têm expressões binários para operações não verificadas, mas a sobrecarga delegado anula a vantagem desmarcada (e então alguns).

Atualmente eu estou convertendo as entradas para UInt64 / Int64 antes de fazer a aritmética, em seguida, converter de volta (com um bit a bit E para garantir in-gama). É cerca de 50% mais lento do que aritmética desmarcada (de acordo com profiling).

Movendo a parte aritmética-sensível para um projeto com o trabalho de força aritmética sem checagem, mas parece um exagero para dar-lhe uma assembleia só para ela.

Foi útil?

Solução

Pessoalmente, acho que deixar isso em sua própria assembleia, especialmente desde que ele vai ser uma pequena montagem tal, é uma boa opção. Isto torna a manutenção mais fácil, já que é fácil de se regenerar esta assembléia a qualquer momento. Basta fazer um assembly separado sinalizado desmarcada, e colocar o seu código sensível ao desempenho lá.

Outras dicas

Eu sei que isso é velho, mas recentemente necessário para converter algum código C # que usado sem controle e eu pensei que iria partilhar como eu fiz isso. É puro código VB e pode ser com escopo no entanto você precisa (em vez de uma opção de todo o projeto).

O truque é criar uma estrutura que contém um campo de comprimento e dois campos inteiros. Em seguida, use StructLayout e FieldOffset atributos para criar uma união da longa e os dois inteiros. Os campos podem (devem) ser privado. Use alargando operadores Ctype converter de um longo para a estrutura e a partir da estrutura de um número inteiro (utilizando o valor baixo número inteiro). Adicionar sobrecargas de operador para +, -, *, etc ... e pronto! aritmética não verificado em VB!

Sort of ... vai ainda estouro, como Strilanc salientou, se o valor de longo vai para fora do intervalo para longs. Mas ele funciona muito bem para um monte de situações em que não verificado é usado.

Aqui está um exemplo:

<StructLayout(LayoutKind.Explicit)>
Public Structure UncheckedInteger

    <FieldOffset(0)>
    Private longValue As Long
    <FieldOffset(0)>
    Private intValueLo As Integer
    <FieldOffset(4)>
    Private intValueHi As Integer

    Private Sub New(newLongValue As Long)
        longValue = newLongValue
    End Sub

    Public Overloads Shared Widening Operator CType(value As Long) As UncheckedInteger
        Return New UncheckedInteger(value)
    End Operator

    Public Overloads Shared Widening Operator CType(value As UncheckedInteger) As Long
        Return value.longValue
    End Operator

    Public Overloads Shared Widening Operator CType(value As UncheckedInteger) As Integer
        Return value.intValueLo
    End Operator

    Public Overloads Shared Operator *(x As UncheckedInteger, y As Integer) As UncheckedInteger
        Return New UncheckedInteger(x.longValue * y)
    End Operator

    Public Overloads Shared Operator Xor(x As UncheckedInteger, y As Integer) As UncheckedInteger
        Return New UncheckedInteger(x.longValue Xor y)
    End Operator

    ' Any other operator overload you need...
End Structure

Use a estrutura no código como este:

Dim x As UncheckedInteger = 2147483647
Dim result As Integer = x * 2  ' This would throw OverflowException using just Integers

Console.WriteLine(result.ToString())  ' -2

cuidado para que seus cálculos não transbordar antes de atribuir o resultado a uma UncheckedInteger. Você poderia criar estruturas UncheckedShort e UncheckedByte usando a mesma técnica.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top