tags:

views:

257

answers:

3

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?

+5  A: 

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:

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

So there is effectively no difference other than possible readability concerns.

Scott Dorman
+2  A: 

Since IntPtr is a value type, using new does not allocate any memory.

Technically, the calls still compile down to different IL - one actually calls the constructor, another calls the explicit conversion operator. 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).

In any case, cast is more idiomatic than using a constructor, so I'd suggest going with it for that reason alone.

Pavel Minaev
The fact that IntPtr is a value type doesn't mean new won't allocate memory. In fact, using new should be preferred to ensure that the struct is properly initialized.
Scott Dorman
I think what Pavel meant, was that it doesn't use any memory that wouldn't have also been used otherwise. Obviously, copying a value type will mean more memory will be used :)
Thorarin
There's absolutely no benefit that using (or not using) `new` will give you to ensure that struct is properly initialized. For starters, you cannot have an "improperly initialized struct" in the first place, since compiler will enforce initialization for locals, and default-initialize everything else.
Pavel Minaev
Also, it is very unlikely that any copying will actually take place here. It will just use a single register (or two on 32-bit machine) to store the value directly, and return it immediately.
Pavel Minaev
Pavel, I realize I wasn't entirely clear by what I meant. If you use a struct that contains public properties rather than fields you will get an "Use of unassigned variable" compiler error if you don't provide values for all of the properties when you use it. You can get around this by newing the struct.public struct T{ public string S { get; set; } public int I { get; set; }}T t;t.S = "hello";Will result in a compiler error, butT t = new T();t.S = "hello";will not.
Scott Dorman
I think you've meant it the other way around (struct that contains public fields rather than properties). In any case, you get around this by _initializing_ the variable, which doesn't have to involve `new` at all. `IntPtr p = (IntPtr)0` will work perfectly well; and, for a generic T, so will `T t = default(T)`.
Pavel Minaev
+3  A: 

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);
    }

}
Hamish Smith