Frage

Diejenigen von uns, die in VB / VB.NET gearbeitet habe habe Code ähnlich wie diesen Gräuel gesehen:

Dim name As String = IIf(obj Is Nothing, "", obj.Name)

Ich sage "Gräuel" für drei einfache Gründe:

  1. IIf ist eine Funktion , werden alle deren Parameter ausgewertet; also wenn obj nichts in dem obigen Aufruf ist, dann wird ein NullReferenceException geworfen werden. Dies ist ein unerwartetes Verhalten für jemanden, der kurzgeschlossen ternäre Operatoren in Sprachen wie C # gewohnt ist.
  2. Da IIf eine Funktion ist, es entsteht somit den Aufwand für einen Funktionsaufruf. Auch wenn dies keine große Sache ist, es funktioniert einfach nicht richtig anfühlen für jemanden, der für sie als ternäre Operation Eigens die Sprache verhalten erwartet.
  3. IIf ist nicht generisch und daher akzeptiert Parameter vom Typ Object, das die folgenden Sprechstellen bedeutet (ich glaube) insgesamt drei ganze Zahlen:

    ' boxes 2nd and 3rd arguments as well as return value '
    Dim value As Integer = IIf(condition, 1, -1)

Nun, in einigen neueren Version von VB.NET (Ich bin nicht sicher, was die Zahl ist) wurde die If Operator eingeführt, die genau die gleiche Art und Weise wie die IIf Funktion funktioniert aber (wie ich es verstehe) ohne die gleichen Mängel auf. Das heißt, es funktioniert bieten Kurzschlüsse und ist ein intrinstic VB Betrieb. Allerdings bin ich über den letzten Teil nicht sicher. Die MSDN-Dokumentation scheint nicht, ob If Boxen seine Argumente, um anzuzeigen, oder nicht. Kennt jemand?

War es hilfreich?

Lösung

Die Hauptsache ist, dass Sie richtig die neue If als identifiziert Operator anstatt eine Funktion. Es ist auch typsicher und deshalb nicht Box braucht, und ist eine direkte Zuordnung zu dem bedingten / ternären /? Operator in C / C ++ / C # / Java / etc

Auch ohne den neuen Betreiber, können Sie eine gewisse Verbesserung in VB.Net mit diesem Code erhalten:

Public Shared Function IIf(Of T)(ByVal Expression As Boolean, ByVal TruePart As T, ByVal FalsePart As T) As T
    If Expression Then Return TruePart Else Return FalsePart
End Function

Andere Tipps

Joel hat mich auf eine Antwort, aber hier ist ein Beispielprogramm und die IL erzeugt, das zeigt, dass, wenn () durch, um den zugrundeliegenden ternären Operator IL ohne Boxen.

Public Class Test
    Public Sub New()
        Dim rnd = New Random()
        Dim result As Integer = If(rnd.Next(1000) < 500, 1, -1)
        Console.WriteLine(result)
    End Sub
End Class

Wie Sie die IL sehen kann, hat keine 'Box' Aussage.

.method public specialname rtspecialname instance void .ctor() cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 result,
        [1] class [mscorlib]System.Random rnd)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: call instance void [mscorlib]System.Object::.ctor()
    L_0007: nop 
    L_0008: newobj instance void [mscorlib]System.Random::.ctor()
    L_000d: stloc.1 
    L_000e: ldloc.1 
    L_000f: ldc.i4 0x3e8
    L_0014: callvirt instance int32 [mscorlib]System.Random::Next(int32)
    L_0019: ldc.i4 500
    L_001e: blt.s L_0023
    L_0020: ldc.i4.m1 
    L_0021: br.s L_0024
    L_0023: ldc.i4.1 
    L_0024: stloc.0 
    L_0025: ldloc.0 
    L_0026: call void [mscorlib]System.Console::WriteLine(int32)
    L_002b: nop 
    L_002c: nop 
    L_002d: ret 
}

das gleiche Programm gegeben, aber mit der älteren IIf () Funktion wird die folgenden IL hergestellt. Sie können sowohl die Boxen sehen, und den Funktionsaufruf Overhead:

.method public specialname rtspecialname instance void .ctor() cil managed
{
    .maxstack 3
    .locals init (
        [0] int32 result,
        [1] class [mscorlib]System.Random rnd)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: call instance void [mscorlib]System.Object::.ctor()
    L_0007: nop 
    L_0008: newobj instance void [mscorlib]System.Random::.ctor()
    L_000d: stloc.1 
    L_000e: ldloc.1 
    L_000f: ldc.i4 0x3e8
    L_0014: callvirt instance int32 [mscorlib]System.Random::Next(int32)
    L_0019: ldc.i4 500
    L_001e: clt 
    L_0020: ldc.i4.1 
    L_0021: box int32
    L_0026: ldc.i4.m1 
    L_0027: box int32
    L_002c: call object [Microsoft.VisualBasic]Microsoft.VisualBasic.Interaction::IIf(bool, object, object)
    L_0031: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToInteger(object)
    L_0036: stloc.0 
    L_0037: ldloc.0 
    L_0038: call void [mscorlib]System.Console::WriteLine(int32)
    L_003d: nop 
    L_003e: nop 
    L_003f: ret 
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top