uipath type threw solucion not net error vb.net ternary-operator boxing

type - ¿El operador "If" de VB.NET causa el boxeo?



object reference not set to an instance of an object was null c# (2)

Aquellos de nosotros que hemos trabajado en VB / VB.NET hemos visto un código similar a esta abominación:

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

Digo "abominación" por tres simples razones:

  1. IIf es una función , todos cuyos parámetros son evaluados; por lo tanto, si obj no es nada en la llamada anterior, se lanzará una NullReferenceException . Este es un comportamiento inesperado para alguien que está acostumbrado a los operadores ternarios cortocircuitados en lenguajes como C #.
  2. Como IIf es una función, incurre en la sobrecarga de una llamada de función. Una vez más, aunque esto no es un gran problema, simplemente no se siente bien para alguien que espera que se comporte como una operación ternaria intrínseca al lenguaje.
  3. IIf no es genérico y, por lo tanto, acepta parámetros de tipo Object , lo que significa que los siguientes cuadros de llamada (creo) tienen un total de tres enteros:

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

Ahora, en una versión más reciente de VB.NET (no estoy seguro de cuál es el número), se introdujo el operador If , que funciona exactamente de la misma manera que la función IIf pero (como lo entiendo) sin los mismos inconvenientes . Es decir, proporciona cortocircuito y es una operación intrínseca de VB. Sin embargo, no estoy seguro de la última parte. La documentación de MSDN no parece indicar si If encuadra sus argumentos o no. ¿Alguien sabe?


Joel me dio una respuesta, pero aquí hay un programa de ejemplo y el IL generado que demuestra que If () pasa al operador ternario subyacente del IL sin boxear.

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

Como puede ver, el IL no tiene una declaración de ''caja''.

.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 }

Dado el mismo programa pero utilizando la antigua función IIf (), se produce la siguiente IL. Puede ver tanto el boxeo como la sobrecarga de llamadas a funciones:

.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 }


Lo principal es que usted identificó correctamente el nuevo If como un operador en lugar de una función. También es de tipo seguro y por lo tanto no necesita boxeo, y es un mapeo directo al condicional / ternario /? Operador en C / C ++ / C # / Java / etc

Incluso sin el nuevo operador, puede obtener algunas mejoras en VB.Net con este código:

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