Since pointers are not allowed on generics, I have to do a lot of GCHandle.Alloc to pin my arrays so that I'm able to do mathematical operations on my arrays. See below an example. The problem is that I always have to use a try...finally construct to Free() the pinned handle again. So it would be nice fi the GCHandle implements and IDisposable so that I can encapsulate it into a using block.
```c#
private unsafe static void OffsetAndScale
{
if ((Math.Abs(scale_in - 1) > float.Epsilon) || (Math.Abs(offset_in) > float.Epsilon))
{
GCHandle aHandle = GCHandle.Alloc(data_in, GCHandleType.Pinned);
void* ptr = aHandle.AddrOfPinnedObject().ToPointer();
int N = data_in.Length;
try
{
switch (Type.GetTypeCode(typeof(Tout)))
{
case TypeCode.Byte:
{
byte* p = (byte*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (byte)((*p * scale_in) + offset_in);
break;
}
case TypeCode.Int16:
{
short* p = (short*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (short)((*p * scale_in) + offset_in);
break;
}
case TypeCode.UInt16:
{
ushort* p = (ushort*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (ushort)((*p * scale_in) + offset_in);
break;
}
case TypeCode.Int32:
{
int* p = (int*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (int)((*p * scale_in) + offset_in);
break;
}
case TypeCode.UInt32:
{
uint* p = (uint*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (uint)((*p * scale_in) + offset_in);
break;
}
case TypeCode.Int64:
{
long* p = (long*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (long)((*p * scale_in) + offset_in);
break;
}
case TypeCode.UInt64:
{
ulong* p = (ulong*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (ulong)((*p * scale_in) + offset_in);
break;
}
case TypeCode.Single:
{
float* p = (float*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (float)((*p * scale_in) + offset_in);
break;
}
case TypeCode.Double:
{
double* p = (double*)ptr;
for (int i = 0; i < N; i++, p++)
*p = (double)((*p * scale_in) + offset_in);
break;
}
}
}
finally
{
if (aHandle.IsAllocated)
{
aHandle.Free();
}
}
}
}
```
Why wouldn't you just use fixed here instead of GCHandle, e.g.
C#
fixed (Tout* ptr = data_in)
{
...
}
@stephentoub: Arghh. Thanks for pointing this out. Originally I used the constrained structand not unmanaged: I was changing this lately for this example and honestly I was not aware that I can use the pointers on unmanaged types now.
Nevertheless. Would it make sense to attach an IDisposable to the GCHandle as a long runner?
I've had this same impulse ever since I first started using GCHandle seven years ago.
This C# 8.0 candidate proposal would enable you to write your own Dispose() extension method for GCHandle to make it work in a using statement.
Thanks @jnm2 . I'm really waiting for the extension everything in C# 8. As you showed in the link it's a good thing. The only problem I have is with the proposal that the structural detection of let's say keywords I personally don't like that much, because it's not so obvious what happens under the hood.
An good example of structural detection that only a few people know is the StaticPropertyChanged what was introduced in .NET 4.5. Of course you have to read through the docs to finds things out, but I prefer some more obvious things.
Most helpful comment
Nevertheless. Would it make sense to attach an IDisposable to the GCHandle as a long runner?