c# - 在 C# 中检查盒装原始整数类型的数值的最快方法

标签 c# .net performance equality primitive

<分区>

我需要编写一个具有以下语义的方法:

/// <summary>
/// Checks if <paramref name="x"/> is a boxed instance of a primitive integral type
/// whose numerical value equals to <paramref name="y"/>.
/// </summary>
/// <param name="x">An object reference. Can be <c>null</c>.</param>
/// <param name="y">A numerical value of type <see cref="ulong"/> to compare with.</param>
/// <returns>
/// <c>true</c> if <paramref name="x"/> refers to a boxed instance of type 
/// <see cref="sbyte"/>, <see cref="short"/>, <see cref="int"/>, <see cref="long"/>, 
/// <see cref="byte"/>, <see cref="ushort"/>, <see cref="uint"/>, or <see cref="ulong"/>, 
/// whose numerical value equals to the numerical value of <paramref name="y"/>; otherwise, <c>false</c>.
/// </returns>
/// <remarks>
/// <para>
/// This method checks only for numeric equality, even if its arguments are of different runtime types
/// (e.g. <c>2L</c> is considered to be equal to <c>2UL</c>).
/// </para>
/// <para>
/// This method returns <c>false</c> if <paramref name="x"/> is <c>null</c>
/// or refers to an instance of a reference type or a boxed instance of a value type except
/// the primitive integral types listed above (e.g. it returns <c>false</c> if <paramref name="x"/>
/// refers to a boxed instance of an <c>enum</c> type, <see cref="bool"/>, <see cref="char"/>, <see cref="IntPtr"/>,
/// <see cref="UIntPtr"/>, <see cref="float"/>, <see cref="double"/>, <see cref="decimal"/>, or <see cref="BigInteger"/>).
/// </para>
/// <para>
/// This method should not throw any exceptions, or cause any observable side-effects
/// (e.g. invoke a method that could modify the state of an object referenced by <paramref name="x"/>). 
/// </para>
/// </remarks>
[Pure]
public static bool NumericalEquals(object x, ulong y)

实现应该尽可能快(假设输入数据没有预期的偏向参数x的某些类型或值),并且不应该使用unsafe 代码或 P/Invoke。当然,在最快的实现中,我更喜欢最简单和最短的实现。

我的解决方案如下:

public static bool NumericalEquals(object x, ulong y)
{
    if (x is sbyte)
    {
        sbyte z = (sbyte)x;
        return z >= 0 && y == (ulong)z;
    }

    if (x is short)
    {
        short z = (short)x;
        return z >= 0 && y == (ulong)z;
    }

    if (x is int)
    {
        int z = (int)x;
        return z >= 0 && y == (ulong)z;
    }

    if (x is long)
    {
        long z = (long)x;
        return z >= 0 && y == (ulong)z;
    }

    if (x is byte)
    {
        return y == (byte)x;
    }

    if (x is ushort)
    {
        return y == (ushort)x;
    }

    if (x is uint)
    {
        return y == (uint)x;
    }

    if (x is ulong)
    {
        return y == (ulong)x;
    }

    return false;
}

您能提出更好的方法吗?

最佳答案

由于每个整数基本类型都是密封的,因此您的引用实现执行的is 操作由 JIT 编译为简单的 RuntimeTypeHandle 之间的相等比较对象 x 的类型(可能通过一个或两个指针取消引用获得)和特定整数类型的句柄(可能实现为内联文字或单个 mov 指令引用固定的内存位置)。在不利用有关方法输入分布的信息的情况下,即使不是不可能,也很难改进初始实现。

关于c# - 在 C# 中检查盒装原始整数类型的数值的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24457881/

相关文章:

.net - 使用委托(delegate)和声明事件

c# - 如何在 Windows 中获取当前用户登录 session 的唯一 ID - c#

java - 使用长变量作为其大小创建长数组时的错误感到困惑

performance - 如果我使用多种字体,是否可以将 Google Web 字体减少到一个请求?

c# - 如何在 Azure 广告 B2C 上使用自定义角色?

c# - var 关键字和使用 namespace

c# - 内置函数 diff() 可用于 MathNet 中的矢量?

c# - Entity Framework 4 - 如何从存储过程读取多个记录集?

c# - 如何将参数传递给带有特殊字符的 WCF Web 服务?

ios - 纵向 View 在 swift 中提供与横向模式相同的宽度