简体   繁体   English

IntPtr演员与新演员

[英]IntPtr cast vs. new

I was just looking at an example, and in it I saw the code 我只是看一个例子,在其中我看到了代码

return new IntPtr(handle);

After poking around our code, I found that we have already used a similar pattern, but in our code we had almost the same thing: 在探索我们的代码之后,我发现我们已经使用了类似的模式,但在我们的代码中我们几乎有相同的东西:

return (IntPtr)handle;

Is there a difference between those two takes? 这两种情况有区别吗? Will the second one be "better" in any way, since it doesn't allocate new memory, or is the cast just hiding the same constructor underneath? 第二个是否会以任何方式“更好”,因为它不会分配新的内存,或者只是隐藏相同的构造函数?

In your examples, I'm guessing handle is an integer value? 在你的例子中,我猜测句柄是一个整数值? IntPtr declares an explicit conversion from Int32 (int) and Int64 (long) which simply calls the same constructor: IntPtr声明从Int32(int)和Int64(long)的显式转换,它只调用相同的构造函数:

public static explicit operator IntPtr(int value)
{
    return new IntPtr(value);
}

So there is effectively no difference other than possible readability concerns. 因此除了可能的可读性问题之外,实际上没有区别。

Reflector says that the cast is calling the constructor under the hood anyway: 反射器说,无论如何,演员都在调用引擎盖下的构造函数:

[Serializable, StructLayout(LayoutKind.Sequential), ComVisible(true)]
public struct IntPtr : ISerializable
{
    ...

    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
    public static explicit operator IntPtr(int value)
    {
        return new IntPtr(value);
    }

}

So this thread is all talk and no numbers so lets talk metrics. 所以这个线程都是谈话而没有数字,所以让我们谈谈指标。 I ran some test code to get some performance metrics using Visual Studio 2010 and 我运行了一些测试代码,以使用Visual Studio 2010获得一些性能指标

I got these metrics by calculating the average time of either method over 10 test runs with 10 million iterations each in Debug then Release mode (non optimized then optimized): 我通过计算10个测试运行中的任一方法的平均时间来获得这些度量,其中每个在Debug然后释放模式中进行1000万次迭代(非优化然后优化):

(Debug) Casting Method: ~32 ms Allocation Method: ~26 ms (调试)转换方法:~32 ms分配方法:~26 ms

(Release) Casting Method: ~20 ms Allocation Method: ~22 ms (发布)投射方法:~20 ms分配方法:~22 ms

What is also interesting is to compare these metrics to similar code with managed C++ only using gcnew and the results are much different. 同样有趣的是,仅使用gcnew将这些指标与托管C ++的类似代码进行比较,结果会有很大差异。

Same setup again. 再次设置相同。 Except comparing the casting method: "IntPtr^ ptr = (IntPtr) i;" 除了比较铸造方法:“IntPtr ^ ptr =(IntPtr)i;” vs the allocation method: "IntPtr^ ptr = (IntPtr) i;". vs分配方法:“IntPtr ^ ptr =(IntPtr)i;”。

(Debug) Casting Method: ~91ms Allocation Method: ~127ms (调试)转换方法:~91ms分配方法:~127ms

(Release) Casting Method: ~22ms Allocation Method: ~124ms (发布)施法方法:~22ms分配方法:~124ms

Now if you are scratching your head saying well why is C# so much faster than managed C++ and the answer is it isn't. 现在,如果你正在轻描淡写地说好,为什么C#比托管C ++快得多,答案是不是。 The most efficient way to use IntPtr is as value type not a reference to a value type. 使用IntPtr的最有效方法是作为值类型而不是对值类型的引用。 For instance like so "IntPtr ptr = (IntPtr) i;". 例如像“IntPtr ptr =(IntPtr)i;”。 This would give you ~24ms (Debug more) or (~22 Release mode). 这将为您提供~24ms(Debug more)或(~22 Release模式)。 See how it was optimized above by the compiler to get the 22ms rather than the 90ms. 看看编译器如何优化它以获得22ms而不是90ms。

Conclusion in C#, unless you are looking at REALLY REALLY tight code it doesn't matter. 在C#中的结论,除非你正在看真正的紧密代码,否则无关紧要。 I think with my code in Release it was actually optimizing the cast right out because commenting out the cast gave the same ~22ms. 我认为我在Release中的代码实际上是在优化演员,因为评论演员给出了相同的~22ms。 But for the most part compiler has your back on this one in C# well at least VS 2010 does. 但是在大多数情况下,编译器会在C#中重新使用这个,至少VS 2010。 However, in Managed C++/CLI if you are looking at code with even minimal performance constraints then watch out. 但是,在托管C ++ / CLI中,如果您正在查看具有最小性能约束的代码,那么请注意。 The compiler will not automatically optimize gcnew allocations to the casting approach and it's almost 6 times faster... I actually ran into this particular problem in C++/CLI which is what led me to post on this thread when dealing with some real-time audio processing. 编译器不会自动优化对cast方法的gcnew分配,而且几乎快了6倍......我实际上遇到了C ++ / CLI中的这个特殊问题,这导致我在处理一些实时音频时发布在这个线程上处理。 My code (C#): (My managed C++ code was very similar except I had to write Average() myself and used console to output rather than message boxes). 我的代码(C#):(我的托管C ++代码非常相似,除了我自己编写Average()并使用控制台输出而不是消息框)。

    static void Main()
    {
        List<int> castTimings = new List<int>();
        List<int> allocTimings = new List<int>();

        for (int i = 0; i < TEST_RUNS; ++i)
        {
            castTimings.Add(RunCastMethod().Milliseconds);
            allocTimings.Add(RunAllocationMethod().Milliseconds);
        }

        MessageBox.Show(string.Format("Casting Method took: {0}ms", castTimings.Average() ));
        MessageBox.Show(string.Format("Allocation Method took: {0}ms", allocTimings.Average() ));
    }

    private static TimeSpan RunAllocationMethod() {
        DateTime start = DateTime.Now;

        for (int i = 0; i < TEST_ITERATIONS; ++i)
        {
            IntPtr ptr = new IntPtr(i);
        }

        return ( DateTime.Now - start );
    }

    private static TimeSpan RunCastMethod()
    {
        DateTime start = DateTime.Now;

        for (int i = 0; i < TEST_ITERATIONS; ++i)
        {
            IntPtr ptr = (IntPtr) i;
        }

        return (DateTime.Now - start);
    }

Since IntPtr is a value type, using new does not allocate any memory. 由于IntPtr是值类型,因此使用new不会分配任何内存。

Technically, the calls still compile down to different IL - one actually calls the constructor, another calls the explicit conversion operator. 从技术上讲,调用仍然编译为不同的IL - 一个实际调用构造函数,另一个调用显式转换运算符。 I'm not sure if there's any actual difference between those two after a JIT pass, however - most likely none (though I doubt you'd notice either way in practice, this being a femtooptimization). 我不确定在JIT通过之后这两者之间是否存在任何实际差异 - 但很可能没有(尽管我怀疑你在实践中注意到这两种方式,这是一种femtooptimization)。

In any case, cast is more idiomatic than using a constructor, so I'd suggest going with it for that reason alone. 无论如何,演员比使用构造函数更惯用,所以我建议单独使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM