هل يتسبب VB.NET "إذا" المشغل للملاكمة؟
-
18-09-2019 - |
سؤال
رأوئون منا الذين عملوا في vb / vb.net قد رأوا كود مماثل لهذه التخزين:
Dim name As String = IIf(obj Is Nothing, "", obj.Name)
أقول "رجس" لأسباب بسيطة:
IIf
هو وظيفة, ، كل من المعلمات التي يتم تقييمها؛ وبالتالي إذاobj
لا شيء في المكالمة أعلاه ثمNullReferenceException
سوف ألقيت. هذا سلوك غير متوقع لشخص اعتاد على مشغلي ثلاثي الدائرة في اللغات مثل C #.- لأن
IIf
هي وظيفة، وبالتالي فإنه يتحمل النفقات العامة لإجراء مكالمة دالة. مرة أخرى، على الرغم من أن هذه ليست مشكلة كبيرة، إلا أنها لا تشعر بالحق في شخص يتوقع أن تتصرف كعملية ثغرية جوهرية للغة. IIf
غير عامة وبالتالي يقبل معلمات النوعObject
, ، مما يعني صناديق المكالمات التالية (أعتقد) ما مجموعه ثلاثة أعداد صحيحة:' boxes 2nd and 3rd arguments as well as return value '
Dim value As Integer = IIf(condition, 1, -1)
الآن، في بعض الإصدار الأخير من VB.NET (لست متأكدا من رقم الرقم)، If
تم تقديم المشغل، الذي يعمل بالضبط بنفس الطريقة مثل IIf
وظيفة ولكن (كما أفهمها) دون أوجه القصور نفسها. وهذا يعني ذلك هل توفير الدائرة القصيرة وذلك يكون عملية vb intrinstic. ومع ذلك، لست متأكدا من الجزء الأخير. ال وثائق MSDN. لا يبدو أن يشير إلى ما إذا كان If
صناديق حججها أم لا. هل يعلم أحد؟
المحلول
الشيء الرئيسي هو أنك حددت بشكل صحيح الجديد If
كما المشغل أو العامل بدلا من وظيفة. كما أنه لا يحتاج إلى ملاكمة، وبالتالي لا يحتاج إلى ملاكمة، وهو رسم خرائط مباشرا على الشرط / القصير /؟ المشغل في C / C ++ / C # / Java / etc
حتى بدون المشغل الجديد، يمكنك الحصول على بعض التحسن في VB.NET مع هذا الرمز:
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
نصائح أخرى
فازت Joel على إجابة، ولكن هنا هو برنامج عينة وإلغاء إيل ينشئ أنه إذا تم () تمر () من خلال المشغل الثلاثي الأساسي ل IL دون ملاكمة.
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
كما ترى IL لا يوجد لديه بيان "مربع".
.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
}
بالنظر إلى نفس البرنامج ولكن باستخدام وظيفة IIF القديمة ()، يتم إنتاج IL التالي. يمكنك أن ترى كل من الملاكمة، ودالة استدعاء النفقات العامة:
.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
}