2010-03-08 10 views
8

Ho un progetto in cui voglio avere controllato l'aritmetica per impostazione predefinita, ad eccezione di un punto sensibile delle prestazioni. Sfortunatamente, VB.Net non ha un blocco 'non controllato'.Il modo più veloce per aggiungere un numero intero non controllato in VB.Net?

Idealmente il framework avrebbe una sorta di tipo intero con aritmetica esplicitamente deselezionata, ma non ho trovato nulla di simile. Ho trovato che gli alberi di espressione hanno espressioni binarie per operazioni non controllate, ma il delegato in testa annulla il vantaggio non controllato (e poi alcuni).

Attualmente sto convertendo gli input in UInt64/Int64 prima di eseguire l'aritmetica, quindi la conversione indietro (con un bit per E per garantire in-range). È circa il 50% più lento dell'aritmetica non controllata (secondo la profilazione).

Spostare la parte aritmetica sensibile in un progetto con aritmetica non controllata potrebbe funzionare, ma sembra eccessivo assumere un assieme tutto per sé.

+1

Un ulteriore assembly C# per questo potrebbe essere eccessivo, ma è anche possibile creare un modulo dal file C# (alcuni parametri della riga di comando per il compilatore) e quindi utilizzare ILmerge per unirlo con l'assembly VB.NET. – OregonGhost

risposta

2

Personalmente, penso che lasciare questo nella propria assemblea, soprattutto perché sarà un assemblaggio così piccolo, è una buona opzione. Ciò semplifica la manutenzione, poiché è facile rigenerare questo assembly in qualsiasi momento. Basta fare in modo che un assieme separato sia deselezionato e inserire lì il proprio codice sensibile al rendimento.

+0

È possibile eseguire l'aritmetica deselezionata in VB. Il problema è che si tratta di un'opzione a livello di progetto (in Opzioni di compilazione avanzate nella scheda Compilazione). –

+0

@Strilanc: Ancora meglio - ha modificato la mia risposta, quindi. Farei un progetto separato per il tuo perf. codice critico, e di riferimento, quindi. –

+4

Ho fatto qualcosa di leggermente diverso: ho scritto tipi con l'aritmetica incontrollato e mettere quelli nel gruppo incontrollato. Ora ho ModByte/ModInt16/ModInt32/ModInt64 e il gruppo non controllato sicuramente non assorbe lentamente il codice. –

3

So che questo è vecchio, ma di recente ho avuto bisogno di convertire un codice C# che fosse deselezionato e ho pensato di condividere come l'ho fatto. È puro codice VB e può essere definito come necessario (piuttosto che un'opzione di progetto).

Il trucco è creare una struttura che contenga un campo Lungo e due campi Integer. Quindi utilizzare gli attributi StructLayout e FieldOffset per creare un'unione dei numeri interi long e two. I campi possono (dovrebbero) essere privati. Utilizzare gli operatori CType di allargamento per convertire da Long alla struttura e dalla struttura a Integer (utilizzando il valore intero basso). Aggiungi sovraccarichi dell'operatore per +, -, *, ecc ... e presto! aritmetica deselezionata in VB!

Un po 'di ... continuerà a traboccare, come sottolineato da Strilanc, se il valore lungo va oltre l'intervallo per i lunghi. Funziona piuttosto bene per un sacco di situazioni in cui viene utilizzato un controllo non selezionato.

Ecco un esempio:

<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 

utilizzare la struttura in codice come questo:

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

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

attenti che i vostri calcoli non lo fanno troppo pieno prima di assegnare il risultato a un UncheckedInteger. È possibile creare strutture UncheckedShort e UncheckedByte utilizzando la stessa tecnica.

+0

Non si riuscirà ancora a traboccare? Cosa succede se si moltiplica per due fino a quando anche l'intervallo del lungo viene superato? –

+0

Il codice come ho postato sarebbe certamente traboccare se il valore lungo è andato al di fuori della sua gamma. Nella mia situazione, non dovevo preoccuparmi di questo.Se il sovraccarico del valore lungo è un problema, è sempre possibile aggiungere controlli di intervallo. –

Problemi correlati