带有Nullable< T>的'=='的参数顺序

编程入门 行业动态 更新时间:2024-10-17 11:31:53
本文介绍了带有Nullable< T>的'=='的参数顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

以下两个C#函数的区别仅在于将参数的左/右顺序交换为等于运算符==. (IsInitialized的类型是bool).使用 C#7.1 和 .NET 4.7 .

The following two C# functions differ only in swapping the left/right order of arguments to the equals operator, ==. (The type of IsInitialized is bool). Using C# 7.1 and .NET 4.7.

static void A(ISupportInitialize x) { if ((x as ISupportInitializeNotification)?.IsInitialized == true) throw null; }

static void B(ISupportInitialize x) { if (true == (x as ISupportInitializeNotification)?.IsInitialized) throw null; }

但是第二个代码的 IL代码似乎要复杂得多.例如, B 是:

But the IL code for the second one seems much more complex. For example, B is:

  • 长36个字节(IL代码);
  • 调用其他功能,包括newobj和initobj;
  • 宣布四个本地人,而只宣布一个.
  • 36 bytes longer (IL code);
  • calls additional functions including newobj and initobj;
  • declares four locals versus just one.
[0] bool flag nop ldarg.0 isinst [System]ISupportInitializeNotification dup brtrue.s L_000e pop ldc.i4.0 br.s L_0013 L_000e: callvirt instance bool [System]ISupportInitializeNotification::get_IsInitialized() L_0013: stloc.0 ldloc.0 brfalse.s L_0019 ldnull throw L_0019: ret

函数"B"的IL ...

[0] bool flag, [1] bool flag2, [2] valuetype [mscorlib]Nullable`1<bool> nullable, [3] valuetype [mscorlib]Nullable`1<bool> nullable2 nop ldc.i4.1 stloc.1 ldarg.0 isinst [System]ISupportInitializeNotification dup brtrue.s L_0018 pop ldloca.s nullable2 initobj [mscorlib]Nullable`1<bool> ldloc.3 br.s L_0022 L_0018: callvirt instance bool [System]ISupportInitializeNotification::get_IsInitialized() newobj instance void [mscorlib]Nullable`1<bool>::.ctor(!0) L_0022: stloc.2 ldloc.1 ldloca.s nullable call instance !0 [mscorlib]Nullable`1<bool>::GetValueOrDefault() beq.s L_0030 ldc.i4.0 br.s L_0037 L_0030: ldloca.s nullable call instance bool [mscorlib]Nullable`1<bool>::get_HasValue() L_0037: stloc.0 ldloc.0 brfalse.s L_003d ldnull throw L_003d: ret

  • A 和 B 之间在功能,语义或其他运行时方面是否有区别? (我们只对此处的正确性感兴趣,而不对性能感兴趣)
  • 如果它们在功能上不是等价的,那么哪些运行时条件可以暴露出明显的差异?
  • 如果它们是功能等效项,则 B 在做什么(总是以与 A 相同的结果结束),以及触发了什么它的痉挛? B 是否具有永远无法执行的分支?
  • 如果通过==的左侧侧出现的差异(此处是引用表达式的属性与文字值)之间的差异来解释差异,您是否可以指出描述细节的C#规范.
  • 是否有可靠的经验法则可用于在编码时预测膨胀的 IL ,从而避免创建它?
  • Is there any functional, semantic, or other substantial runtime difference between A and B? (We're only interested in correctness here, not performance)
  • If they are not functionally equivalent, what are the runtime conditions that can expose an observable difference?
  • If they are functional equivalents, what is B doing (that always ends up with the same result as A), and what triggered its spasm? Does B have branches that can never execute?
  • If the difference is explained by the difference between what appears on the left side of ==, (here, a property referencing expression versus a literal value), can you indicate a section of the C# spec that describes the details.
  • Is there a reliable rule-of-thumb that can be used to predict the bloated IL at coding-time, and thus avoid creating it?
  • 奖金.每个堆栈的最终最终JITted x86或AMD64代码如何?

    BONUS. How does the respective final JITted x86 or AMD64 code for each stack up?

    基于注释反馈的其他注释.首先,提出了第三个变体,但它给出与 A 相同的IL(对于Debug和Release构建).顺便说一句,新版本的 C#似乎比 A 更漂亮:

    [edit] Additional notes based on feedback in the comments. First, a third variant was proposed, but it gives identical IL as A (for both Debug and Release builds). Sylistically, however, the C# for the new one does seem sleeker than A:

    static void C(ISupportInitialize x) { if ((x as ISupportInitializeNotification)?.IsInitialized ?? false) throw null; }

    这里也是每个功能的Release IL.请注意,对于Release IL, A / C 与 B 的不对称性仍然很明显,因此原始问题仍然存在. 释放功能'A','C'的IL ...

    Here also is the Release IL for each function. Note that the asymmetry A/C vs. B is still evident with the Release IL, so the original question still stands.

    ldarg.0 isinst [System]ISupportInitializeNotification dup brtrue.s L_000d pop ldc.i4.0 br.s L_0012 L_000d: callvirt instance bool [System]ISupportInitializeNotification::get_IsInitialized() brfalse.s L_0016 ldnull throw L_0016: ret

    释放功能'B'的IL ...

    [0] valuetype [mscorlib]Nullable`1<bool> nullable, [1] valuetype [mscorlib]Nullable`1<bool> nullable2 ldc.i4.1 ldarg.0 isinst [System]ISupportInitializeNotification dup brtrue.s L_0016 pop ldloca.s nullable2 initobj [mscorlib]Nullable`1<bool> ldloc.1 br.s L_0020 L_0016: callvirt instance bool [System]ISupportInitializeNotification::get_IsInitialized() newobj instance void [mscorlib]Nullable`1<bool>::.ctor(!0) L_0020: stloc.0 ldloca.s nullable call instance !0 [mscorlib]Nullable`1<bool>::GetValueOrDefault() beq.s L_002d ldc.i4.0 br.s L_0034 L_002d: ldloca.s nullable call instance bool [mscorlib]Nullable`1<bool>::get_HasValue() L_0034: brfalse.s L_0038 ldnull throw L_0038: ret

    最后,提到了使用新的 C#7 语法的版本,该版本似乎产生了最干净的IL:

    Lastly, a version using new C# 7 syntax was mentioned which seems to produce the cleanest IL of all:

    static void D(ISupportInitialize x) { if (x is ISupportInitializeNotification y && y.IsInitialized) throw null; }

    释放功能'D'的IL ...

    [0] class [System]ISupportInitializeNotification y ldarg.0 isinst [System]ISupportInitializeNotification dup stloc.0 brfalse.s L_0014 ldloc.0 callvirt instance bool [System]ISupportInitializeNotification::get_IsInitialized() brfalse.s L_0014 ldnull throw L_0014: ret

    推荐答案

    所以我很好奇答案,并研究了c#6规范(不知道c#7规范的托管位置).完全免责声明:我不保证我的回答是正确的,因为我没有编写c#规范/编译器,并且我对内部结构的理解受到限制.

    So I was curious about the answer and took a look at the c# 6 specification (no clue where the c# 7 spec is hosted). Full disclaimer: I do not guarantee that my answer is correct, because I did not write the c# spec/compiler and my understanding of the internals is limited.

    但我认为答案在于可重载 ==运算符. ==的最佳适用重载是通过使用更好的功能成员.

    Yet I think that the answer lies in the resultion of the overloadable == operator. The best applicable overload for == is determined by using the rules for better function members.

    根据规格:

    给出一个带有一组参数表达式{E1,E2, ...,En}和两个适用的带有参数的函数成员Mp和Mq 类型{P1,P2,...,Pn}和{Q1,Q2,...,Qn},Mp定义为 比Mq更好的功能成员

    Given an argument list A with a set of argument expressions {E1, E2, ..., En} and two applicable function members Mp and Mq with parameter types {P1, P2, ..., Pn} and {Q1, Q2, ..., Qn}, Mp is defined to be a better function member than Mq if

    对于每个参数,从Ex到Qx的隐式转换并不更好 比从Ex到Px的隐式转换,并且至少要转换一个 参数,从Ex到Px的转换要好于转换 从Ex到Qx.

    for each argument, the implicit conversion from Ex to Qx is not better than the implicit conversion from Ex to Px, and for at least one argument, the conversion from Ex to Px is better than the conversion from Ex to Qx.

    引起我注意的是参数列表{E1, E2, .., En}.如果将Nullable<bool>与bool进行比较,则参数列表应该类似于{Nullable<bool> a, bool b},对于该参数列表,Nullable<bool>.Equals(object o)方法似乎是最好的功能,因为它只需要从bool进行一次隐式转换.到object.

    What caught my eye is the argument list {E1, E2, .., En}. If you compare a Nullable<bool> to a bool the argument list should be something like {Nullable<bool> a, bool b}and for that argument list the Nullable<bool>.Equals(object o) method seems to be the best function, because it only takes one implicit conversion from bool to object.

    但是,如果将参数列表的顺序恢复为{bool a, Nullable<bool> b},则Nullable<bool>.Equals(object o)方法不再是最好的功能,因为现在您必须在第一个参数中将Nullable<bool>转换为bool在第二个参数中从bool到object.这就是为什么对于情况 A 选择了不同的重载,这似乎会导致更清晰的IL代码.

    However if you revert the order of the argument list to {bool a, Nullable<bool> b} the Nullable<bool>.Equals(object o) method no longer is the best function, because now you would have to convert from Nullable<bool> to bool in the first argument and then from bool to object in the second argument. That's why for case A a different overload is selected which seems to result in cleaner IL code.

    再次说明,这是我对好奇心的满足,并且似乎符合c#规范.但是我还没有弄清楚如何调试编译器以了解实际情况.

    Again this is an explanation that satisfies my own curiosity and seems to be in line with the c# spec. But I have yet to figure out how to debug the compiler to see what's actually going on.

    更多推荐

    带有Nullable&lt; T&gt;的'=='的参数顺序

    本文发布于:2023-11-02 14:17:53,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1552634.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:顺序   参数   amp   Nullable   lt

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!