I'm looking for a way to reinterpret an array of type byte[] as a different type, say short[]. In C++ this would be achieved by a simple cast but in C# I haven't found a way to achieve this without resorting to duplicating the entire buffer.
Any ideas?
You can achieve this but this is a relatively bad idea. Raw memory access like this is not type-safe and can only be done under a full trust security environment. You should never do this in a properly designed managed application. If your data is masquerading under two different forms, perhaps you actually have two separate data sets?
In any case, here is a quick and simple code snippet to accomplish what you asked:
byte[] bytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int byteCount = bytes.Length;
unsafe
{
// By using the fixed keyword, we fix the array in a static memory location.
// Otherwise, the garbage collector might move it while we are still using it!
fixed (byte* bytePointer = bytes)
{
short* shortPointer = (short*)bytePointer;
for (int index = 0; index < byteCount / 2; index++)
{
Console.WriteLine("Short {0}: {1}", index, shortPointer[index]);
}
}
}
There are four good answers to this question. Each has different downsides. Of course, beware of endianness and realize that all of these answers are holes in the type system, just not particularly treacherous holes. In short, don't do this a lot, and only when you really need to.
Sander's answer. Use unsafe code to reinterpret pointers. This is the fastest solution, but it uses unsafe code. Not always an option.
Leonidas' answer. Use StructLayout and FieldOffset(0) to turn a struct into a union. The downsides to this are that some (rare) environments don't support StructLayout (eg Flash builds in Unity3D) and that StructLayout cannot be used with generics.
ljs' answer. Use BitConverter methods. This has the disadvantage that most of the methods allocate memory, which isn't great in low-level code. Also, there isn't a full suite of these methods, so you can't really use it generically.
Buffer.BlockCopy two arrays of different types. The only downside is that you need two buffers, which is perfect when converting arrays, but a pain when casting a single value. Just beware that length is specified in bytes, not elements. Buffer.ByteLength helps. Also, it only works on primitives, like ints, floats and bools, not structs or enums.
But you can do some neat stuff with it.
public static class Cast {
private static class ThreadLocalType<T> {
[ThreadStatic]
private static T[] buffer;
public static T[] Buffer
{
get
{
if (buffer == null) {
buffer = new T[1];
}
return buffer;
}
}
}
public static TTarget Reinterpret<TTarget, TSource>(TSource source)
{
TSource[] sourceBuffer = ThreadLocalType<TSource>.Buffer;
TTarget[] targetBuffer = ThreadLocalType<TTarget>.Buffer;
int sourceSize = Buffer.ByteLength(sourceBuffer);
int destSize = Buffer.ByteLength(targetBuffer);
if (sourceSize != destSize) {
throw new ArgumentException("Cannot convert " + typeof(TSource).FullName + " to " + typeof(TTarget).FullName + ". Data types are of different sizes.");
}
sourceBuffer[0] = source;
Buffer.BlockCopy(sourceBuffer, 0, targetBuffer, 0, sourceSize);
return targetBuffer[0];
}
}
class Program {
static void Main(string[] args)
{
Console.WriteLine("Float: " + Cast.Reinterpret<int, float>(100));
Console.ReadKey();
}
}
c# supports this so long as you are willing to use unsafe code but only on structs.
for example : (The framework provides this for you but you could extend this to int <-> uint conversion
public unsafe long DoubleToLongBits(double d)
{
return *((long*) (void*) &d);
}
Since the arrays are reference types and hold their own metadata about their type you cannot reinterpret them without overwriting the metadata header on the instance as well (an operation likely to fail).
You can howveer take a foo* from a foo[] and cast that to a bar* (via the technique above) and use that to iterate over the array. Doing this will require you pin the original array for the lifetime of the reinterpreted pointer's use.
You could wrap your shorts/bytes into a structure which allows you to access both values:
See also here: C++ union in C#
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace TestShortUnion {
[StructLayout(LayoutKind.Explicit)]
public struct shortbyte {
public static implicit operator shortbyte(int input) {
if (input > short.MaxValue)
throw new ArgumentOutOfRangeException("input", "shortbyte only accepts values in the short-range");
return new shortbyte((short)input);
}
public shortbyte(byte input) {
shortval = 0;
byteval = input;
}
public shortbyte(short input) {
byteval = 0;
shortval = input;
}
[FieldOffset(0)]
public byte byteval;
[FieldOffset(0)]
public short shortval;
}
class Program {
static void Main(string[] args) {
shortbyte[] testarray = new shortbyte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1111 };
foreach (shortbyte singleval in testarray) {
Console.WriteLine("Byte {0}: Short {1}", singleval.byteval, singleval.shortval);
}
System.Console.ReadLine();
}
}
}
You can use System.Memory to do this in a safe way.
public static TTo[] Cast<TFrom, TTo>(this TFrom[] source) where TTo : struct where TFrom : struct =>
MemoryMarshal.Cast<TFrom, TTo>(source).ToArray();
private byte[] CastToBytes(int[] foo) => foo.Cast<int, byte>(foo);
This kind of behaviour would result in C# being rather type-unsafe. You can easily achieve this in a type-safe manner, however (though of course you are copying the array in doing so).
If you want one byte to map to one short then it's simple using ConvertAll, e.g.:-
short[] shorts = Array.ConvertAll(bytes, b => (short)b);
If you want to simply map every 2 bytes to a short then the following should work:-
if (bytes.Length % 2 != 0)
{
throw new ArgumentException("Byte array must have even rank.");
}
short[] shorts = new short[bytes.Length / 2];
for (int i = 0; i < bytes.Length / 2; ++i)
{
shorts[i] = BitConverter.ToInt16(bytes, 2*i);
}
It may be possible to use the marshaller to do some weird bit-twiddling to achieve this, probably using an unsafe { ... } code block, though this would be prone to errors and make your code unverifiable.
I suspect what you're trying to do can be achieved better using a type-safe idiom rather than a type-unsafe C/C++ one!
Update: Updated to take into account comment.
Casting like this is fundamentally unsafe and not permitted in a managed language. That's also why C# doesn't support unions. Yes, the workaround is to use the Marshal class.
Wouldn't it be possible to create a collection class that implements an interface for both bytes and shorts? Maybe implement both IList< byte > and IList< short >? Then you can have your underlying collection contain bytes, but implement IList< short > functions that work on byte pairs.
I used the code from FastArraySerializer to create a type converter to get from SByte[] to Double[]
public unsafe class ConvertArrayType
{
[StructLayout(LayoutKind.Explicit)]
private struct Union
{
[FieldOffset(0)] public sbyte[] sbytes;
[FieldOffset(0)] public double[] doubles;
}
private Union _union;
public double[] doubles {
get { return _union.doubles; }
}
public sbyte[] sbytes
{
get { return _union.sbytes; }
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct ArrayHeader
{
public UIntPtr type;
public UIntPtr length;
}
private readonly UIntPtr SBYTE_ARRAY_TYPE;
private readonly UIntPtr DOUBLE_ARRAY_TYPE;
public ConvertArrayType(Array ary, Type newType)
{
fixed (void* pBytes = new sbyte[1])
fixed (void* pDoubles = new double[1])
{
SBYTE_ARRAY_TYPE = getHeader(pBytes)->type;
DOUBLE_ARRAY_TYPE = getHeader(pDoubles)->type;
}
Type typAry = ary.GetType();
if (typAry == newType)
throw new Exception("No Type change specified");
if (!(typAry == typeof(SByte[]) || typAry == typeof(double[])))
throw new Exception("Type Not supported");
if (newType == typeof(Double[]))
{
ConvertToArrayDbl((SByte[])ary);
}
else if (newType == typeof(SByte[]))
{
ConvertToArraySByte((Double[])ary);
}
else
{
throw new Exception("Type Not supported");
}
}
private void ConvertToArraySByte(double[] ary)
{
_union = new Union { doubles = ary };
toArySByte(_union.doubles);
}
private void ConvertToArrayDbl(sbyte[] ary)
{
_union = new Union { sbytes = ary };
toAryDouble(_union.sbytes);
}
private ArrayHeader* getHeader(void* pBytes)
{
return (ArrayHeader*)pBytes - 1;
}
private void toAryDouble(sbyte[] ary)
{
fixed (void* pArray = ary)
{
var pHeader = getHeader(pArray);
pHeader->type = DOUBLE_ARRAY_TYPE;
pHeader->length = (UIntPtr)(ary.Length / sizeof(double));
}
}
private void toArySByte(double[] ary)
{
fixed (void* pArray = ary)
{
var pHeader = getHeader(pArray);
pHeader->type = SBYTE_ARRAY_TYPE;
pHeader->length = (UIntPtr)(ary.Length * sizeof(double));
}
}
} // ConvertArrayType{}
Here's the VB usage:
Dim adDataYgch As Double() = Nothing
Try
Dim nGch As GCHandle = GetGch(myTag)
If GCHandle.ToIntPtr(nGch) <> IntPtr.Zero AndAlso nGch.IsAllocated Then
Dim asb As SByte()
asb = CType(nGch.Target, SByte())
Dim cvt As New ConvertArrayType(asb, GetType(Double()))
adDataYgch = cvt.doubles
End If
Catch ex As Exception
Debug.WriteLine(ex.ToString)
End Try
Related
I know languages such as C and C++ allow determining the size of data (structs, arrays, variables...) at runtime using sizeof() function. I tried that in C# and apparently it does not allow putting variables into the sizeof() function, but type defintions only (float, byte, Int32, uint, etc...), how am I supposed to do that?
Practically, I want this to happen:
int x;
Console.WriteLine(sizeof(x)); // Output: 4
AND NOT:
Console.WriteLine(sizeof(int)); // Output: 4
I'm sure there's some normal way to get the size of data at runtime in C#, yet google didn't give much help.. Here it is my last hope
Following on from Cory's answer, if performance is important and you need to hit this code a lot then you could cache the size so that the dynamic method only needs to be built and executed once per type:
int x = 42;
Console.WriteLine(Utils.SizeOf(x)); // Output: 4
// ...
public static class Utils
{
public static int SizeOf<T>(T obj)
{
return SizeOfCache<T>.SizeOf;
}
private static class SizeOfCache<T>
{
public static readonly int SizeOf;
static SizeOfCache()
{
var dm = new DynamicMethod("func", typeof(int),
Type.EmptyTypes, typeof(Utils));
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Sizeof, typeof(T));
il.Emit(OpCodes.Ret);
var func = (Func<int>)dm.CreateDelegate(typeof(Func<int>));
SizeOf = func();
}
}
}
To find the size of an arbitrary variable, x, at runtime you can use Marshal.SizeOf:
System.Runtime.InteropServices.Marshal.SizeOf(x)
As mentioned by dtb, this function returns the size of the variable after marshalling, but in my experience that is usually the size you want, as in a pure managed environment the size of a variable is of little interest.
The size of int is always going to be 32 bits. Why would you need to get the size at runtime?
With that said, you could use Marshal.SizeOf(), but that's really intended for unmanaged code only.
I stumbled upon some code that apparently will give you the size of a value type. It uses reflection and would be quite an expensive method call compared to the functionality you wanted to use (sizeof()):
using System;
using System.Reflection;
using System.Reflection.Emit;
...
// GetManagedSize() returns the size of a structure whose type
// is 'type', as stored in managed memory. For any reference type
// this will simply return the size of a pointer (4 or 8).
public static int GetManagedSize(Type type)
{
// all this just to invoke one opcode with no arguments!
var method = new DynamicMethod("GetManagedSizeImpl", typeof(uint), new Type[0], typeof(TypeExtensions), false);
ILGenerator gen = method.GetILGenerator();
gen.Emit(OpCodes.Sizeof, type);
gen.Emit(OpCodes.Ret);
var func = (Func<uint>)method.CreateDelegate(typeof(Func<uint>));
return checked((int)func());
}
If you are doing something like building data packets to send to a device, try this:
byte[] dataBytes = BitConverter.GetBytes(x);
int dataLength = dataBytes.Length;
Now you can, for example, copy the dataBytes array to the Payload section of the dataPacket array, and dataLength will tell you how many bytes to copy, and let you validate or set the PayloadLength value in your data packet.
I was going to say use type inference to meet your requirement ("if you change the type of x from int to say long long, you don't have to replace every occurrence of sizeof(int) with sizeof(long long)"):
public unsafe void GetSizeOf<T>(T exemplar)
where T : struct
{
return sizeof(T);
}
But you can't do that, because T might be a "managed type" -- it might be a struct with an object reference field. There doesn't seem to be a way to constrain T to only unmanaged types.
You could use a static helper class:
public static class Size
{
public int Of(int x)
{
return sizeof(int);
}
public int Of(long x)
{
return sizeof(long);
}
public unsafe int Of(MyStruct x)
{
//only works if MyStruct is unmanaged
return sizeof(MyStruct);
}
}
public class Program
{
public void Main()
{
int x = 0;
Console.WriteLine(Size.Of(x));
}
public void OldMain()
{
long x = 0;
Console.WriteLine(Size.Of(x));
}
}
Went ahead and added some safety/performance/convenience features to the code CORY posted, for the less paranoid LukeH's code should suffice.
In short this class returns type sizes, ensuring a cache is used whenever possible, wrapping up exceptions from external classes as it goes.
You may want to rewrite the catch-all blocks to better suit your project.
/* A class for finding the sizes of types and variables */
public static class Sizes
{
/* Retrieves the size of the generic type T
Returns the size of 'T' on success, 0 otherwise */
public static int SizeOf<T>()
{
return FetchSizeOf(typeof(T));
}
/* Retrieves the size of the type of obj
Returns the size of 'obj' on success, 0 otherwise */
public static int SizeOf<T>(T obj)
{
return FetchSizeOf(typeof(T));
}
/* Retrieves the size of 'type'
Returns the size of 'type' on success, 0 otherwise */
public static int SizeOf(this Type type)
{
return FetchSizeOf(type);
}
/* Gets the size of the specified type
Returns the size of 'type' on success, 0 otherwise*/
private static int FetchSizeOf(this Type type)
{
if ( typeSizeCache == null )
CreateCache();
if ( typeSizeCache != null )
{
int size = 0;
if ( GetCachedSizeOf(type, out size) )
return size;
else
return CalcAndCacheSizeOf(type);
}
else
return CalcSizeOf(type);
}
/* Attempts to get the size of type from the cache
Returns true and sets size on success, returns
false and sets size to 0 otherwise. */
private static bool GetCachedSizeOf(Type type, out int size)
{
size = 0;
try
{
if ( type != null )
{
if ( !typeSizeCache.TryGetValue(type, out size) )
size = 0;
}
}
catch
{
/* - Documented: ArgumentNullException
- No critical exceptions. */
size = 0;
}
return size > 0;
}
/* Attempts to calculate the size of 'type', and caches
the size if it is valid (size > 0)
Returns the calclated size on success, 0 otherwise */
private static int CalcAndCacheSizeOf(Type type)
{
int typeSize = 0;
try
{
typeSize = CalcSizeOf(type);
if ( typeSize > 0 )
typeSizeCache.Add(type, typeSize);
}
catch
{
/* - Documented: ArgumentException, ArgumentNullException,
- Additionally Expected: OutOfMemoryException
- No critical exceptions documented. */
}
return typeSize;
}
/* Calculates the size of a type using dynamic methods
Return the type's size on success, 0 otherwise */
private static int CalcSizeOf(this Type type)
{
try
{
var sizeOfMethod = new DynamicMethod("SizeOf", typeof(int), Type.EmptyTypes);
var generator = sizeOfMethod.GetILGenerator();
generator.Emit(OpCodes.Sizeof, type);
generator.Emit(OpCodes.Ret);
var sizeFunction = (Func<int>)sizeOfMethod.CreateDelegate(typeof(Func<int>));
return sizeFunction();
}
catch
{
/* - Documented: OutOfMemoryException, ArgumentNullException,
ArgumentException, MissingMethodException,
MethodAccessException
- No critical exceptions documented. */
}
return 0;
}
/* Attempts to allocate the typeSizesCache
returns whether the cache is allocated*/
private static bool CreateCache()
{
if ( typeSizeCache == null )
{
try
{
typeSizeCache = new Dictionary<Type, int>();
}
catch
{
/* - Documented: OutOfMemoryException
- No critical exceptions documented. */
typeSizeCache = null;
}
}
return typeSizeCache != null;
}
/* Static constructor for Sizes, sets typeSizeCache to null */
static Sizes()
{
CreateCache();
}
/* Caches the calculated size of various types */
private static Dictionary<Type, int> typeSizeCache;
}
public static class TypeSize
{
public static int GetSize<T>(this T value)
{
if (typeof(T).IsArray)
{
var elementSize = GetTypeSize(typeof(T).GetElementType());
var length = (value as Array)?.GetLength(0);
return length.GetValueOrDefault(0) * elementSize;
}
return GetTypeSize(typeof(T));
}
static ConcurrentDictionary<Type, int> _cache = new ConcurrentDictionary<Type, int>();
static int GetTypeSize(Type type)
{
return _cache.GetOrAdd(type, _ =>
{
var dm = new DynamicMethod("SizeOfType", typeof(int), new Type[0]);
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Sizeof, type);
il.Emit(OpCodes.Ret);
return (int)dm.Invoke(null, null);
});
}
}
Starting with netcore1.0 there is System.Runtime.CompilerServices.Unsafe.SizeOf method that gives you size of any object. Method is implemented in the runtime so it should be very fast.
Note: seems that method returns pointer size (sizeof(IntPtr)) for reference type instead of actual size
Usage:
Console.WriteLine(Unsafe.SizeOf<System.Guid>()); // 16
I'm attempting to P Invoke a C library for use on a Xamarin android app.
Consider the following C structure:
typedef struct
{
bool myBool;
myOtherStruct sOtherStruct;
int myInt;
float myFloat;
float myFloatArray[1024];
float myFloatArray2[1024];
float myFloatArray3[20];
float myFloatArray4[30];
} sMyStruct;
This is called using the following function:
unsigned int initialise(sMyStruct* a_pMyStruct)
I've put this into a C# structure:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct SMyStruct
{
bool myBool;
myOtherStruct sOtherStruct;
int myInt;
float myFloat;
public fixed float myFloatArray[1024];
public fixed float myFloatArray2[1024];
public fixed float myFloatArray3[20];
public fixed float myFloatArray4[30];
public unsafe float[] MyFloatArray
{
get
{
fixed (float* ptr = myFloatArray)
{
float[] array = new float[1024];
Marshal.Copy((IntPtr)ptr, array, 0, 1024 * sizeof(float));
return array;
}
}
}
public SMyStruct (bool MyBool, myOtherStruct otherStruct, int MyInt, float MyFloat)
{
myBool = MyBool;
sOtherStruct = myOtherStruct;
myInt = MyInt;
myFloat = MyFloat;
}
Here's my function in C# to invoke this:
[DllImport("libMylib")]
private static extern unsafe uint initialise(SMyStruct* a_pMyStruct);
I then call this function with:
public unsafe void init ()
{
SMyStruct initStruct;
uint result = initialise(&initStruct);
}
So what happens is the C function will return my structure with A LOT of data. I then pass the structure again into another C routine which uses these parameters for the rest of the program.
My issue is how do I get the float array data back into the correct structure variable so that I can pass it again? At current my code has been based on these questions:
Marshalling float Array to c# and
Marshalling complex struct to c#
But I've not managed to code this so I can pass the float array back to my struct without even seeing a compiler error (let alone failing when I test it!)
How do I get the float array data into my structure?
EDIT
After a couple of answers and comments, I'm adding what I was doing initially to try and add some clarity.
I get a compiler error when rather than using the "public unsafe float[]..." routine above I do this (within the struct):
public SMyStruct (bool MyBool, myOtherStruct otherStruct, int MyInt, float MyFloat, float* MyFloatArray, float* MyFloatArray2, float* MyFloatArray3, float* MyFloatArray4)
{
myBool = MyBool;
sOtherStruct = myOtherStruct;
myInt = MyInt;
myFloat = MyFloat;
myFloatArray = MyFloatArray;
myFloatArray2 = MyFloatArray2;
myFloatArray3 = MyFloatArray3;
myFloatArray4 = MyFloatArray4;
}
With this code I get the error "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"
At this point I attempted to use the copy routine instead.
What I want is to ensure the fields myFloatArray, myFloatArray2 etc. to be populated with whatever the initialise function returns. FYI myBool, sOtherStruct etc. are populated as I expect.
If you don't need to access the data you can leave it as a pointer. Although it looks like you're responsible for the memory, so you'll need to alloc and later free the unmanaged memory you are using. Something like...
[DllImport("libMylib")]
private static extern uint initialise(IntPtr a_pMyStruct);
[DllImport("libMylib")]
private static extern uint anotherNativeMethod(IntPtr a_pMyStruct);
//...
//How big is myOtherStruct??
int size = 1 + ?? + 4 + 4 + (1024*4) + (1024*4) + (20*4) + (30*4);
//int size = Marhsal.SizeOf(SMyStruct);
IntPtr pMyStruct = Marshal.AllocHGlobal(size);
initialise(pMyStruct);
anotherNativeMethod(pMyStruct);
Marshal.FreeHGlobal(pMyStruct);
Note that you can still use the get the Marshaller to copy the pointer to your structure using Marshal.PtrToStructure but you no longer need to depend on it for your code.
I suspect that many of your problems are caused by you attempting to run before you can walk. You have attempted to make a complex struct with many members. Make a single mistake in one place, and nothing works anywhere.
So, how can we simplify? Well, the question you ask relates to the fixed buffers. To paraphrase the question you are asking:
How can I copy an array to and from a fixed buffer?
Let's deal with that by working with a simplified type that only contains a fixed buffer, and prove that we can copy to and from that buffer.
Your property getter is along the right lines. The biggest problem is that you pass an incorrect length. The final argument of the Marshal.Copy overload that you are calling is the number of elements. You erroneously pass the number of bytes. The setter is very similar in nature to the getter. It all looks like this:
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
public unsafe struct MyStruct
{
private const int floatArrayLength = 4;
private fixed float _floatArray[floatArrayLength];
public float[] floatArray
{
get
{
float[] result = new float[floatArrayLength];
fixed (float* ptr = _floatArray)
{
Marshal.Copy((IntPtr)ptr, result, 0, floatArrayLength);
}
return result;
}
set
{
int length = Math.Min(floatArrayLength, value.Length);
fixed (float* ptr = _floatArray)
{
Marshal.Copy(value, 0, (IntPtr)ptr, length);
for (int i = length; i < floatArrayLength; i++)
ptr[i] = 0;
}
}
}
}
class Program
{
static void WriteArray(float[] arr)
{
foreach (float value in arr)
{
Console.Write(value);
Console.Write(" ");
}
Console.WriteLine();
}
static void Main(string[] args)
{
MyStruct myStruct = new MyStruct();
WriteArray(myStruct.floatArray);
myStruct.floatArray = new float[] { 1, 2, 3, 4 };
WriteArray(myStruct.floatArray);
myStruct.floatArray = new float[] { 5, 6 };
WriteArray(myStruct.floatArray);
Console.ReadLine();
}
}
}
The output of the program is:
0 0 0 0
1 2 3 4
5 6 0 0
This building block shows you how to handle your fixed buffers. You can use the code from this program and be sure that the fixed buffers are handled correctly. When you move to a more complex structure, if you have any problems you can be confident that they are not related to the fixed buffer code.
I'm porting a C++ application to C# and experiencing some issues with pointers.
What I'm trying to achieve is to pass an array pointer with an offset so the passed function can work on the correct part of an array. I don't want to change the function's signature to add an extra value for the offset.
So, this is an example piece of C++ code I would like to pass in C#:
void DoSomething( double p[] )
{
p[0] = 0.4;
p[1] = 0.4;
}
int main()
{
double Vector[3];
Vector[0] = 0.2;
Vector[1] = 0.2;
Vector[2] = 0.2;
DoSomething( &Vector[1] );
}
How could I do that ? Keeping in mind that I can't pass the offset ?
[Edit]
Thank you all for the answers.
First, I have to apologize: I made a big mistake while copying the code.
I wrote
DoSomething( Vector[1] );
on last line instead of
DoSomething( &Vector[1] );
this has been corrected.
I then realized that I was not very clear about the signature.
I can slightly change the signature of the function, but I can't add any arguments
I am already using the "unsafe" and "fixed" keywords, so it won't hurt me
It doesn't need to be efficient code since this porting is intended to be a Quick & Dirty implementation of an algorithm written by somebody else for a prototype project. If the project is a "Ok go", the code would be thrown at garbage and rewritten in a C++ dll.
The function "DoSomething" is actually a nest of a few other functions, it is designed as a fast math work but sadly, I don't have all the knowledge about to code it myself. That's why I assume the author has nicely designed its function since it's used world-wide.
I'll try with Servy's suggestion and come back to you in a few days when I'll get back.
It's impossible to do without changing the signature of DoSomething at all, but you can avoid needing to pass along both an array and it's offset side by side all over the place. You can do that by creating a class that composes an array and also keeps track of an offset:
public class ArrayReference<T> : IEnumerable<T>
{
//you can keep these entirely private if you prefer
public T[] Array { get; private set; }
public int Offset { get; private set; }
public ArrayReference(T[] array, int offset)
{
Array = array;
Offset = offset;
}
public T this[int index]
{
get
{
return Array[index + Offset];
}
set
{
Array[index + Offset] = value;
}
}
public int Length
{
get
{
return Array.Length - Offset;
}
}
public IEnumerator<T> GetEnumerator()
{
for (int i = Offset; i < Array.Length; i++)
yield return Array[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public static ArrayReference<T> operator +(
ArrayReference<T> reference, int offset)
{
return new ArrayReference<T>(reference.Array, reference.Offset + offset);
}
public static ArrayReference<T> operator -(
ArrayReference<T> reference, int offset)
{
return new ArrayReference<T>(reference.Array, reference.Offset - offset);
}
public static implicit operator ArrayReference<T>(T[] array)
{
return new ArrayReference<T>(array, 0);
}
public static implicit operator T[](ArrayReference<T> reference)
{
return reference.ToArray();
}
}
You may want to add additional functionality to this, based on your specific needs. You can expose as much or as little of the underlying array's functionality as you need/want.
This is actually not the way you would do it in C#.
The only way to do this is to use unsafe code, and even then it wouldn't be a good implementation, because your method would be unsafe, and your array must be fixed.
The fixed keyword would prevent your array to be moved in another place in memory by the garbage collector, but it could lead to partitioned memory and then worse performance.
Moreover, even by design this isn't a good thing, because you don't know your array boundaries in your method.
But if you really want to do this, go with the enumerators.
In your main method:
double[] d = new double[3];
d[0] = 1.0;
d[1] = 2.0;
d[2] = 3.0;
IEnumerator<double> e = d.AsEnumerable().GetEnumerator();
e.MoveNext();
tryEnumerate(e);
and then your DoSomething method:
static void DoSomething(IEnumerator<double> e)
{
while(e.MoveNext())
Console.WriteLine(e.Current.ToString());
}
Code updated to show chaining using extension methodology. You can easly return any and all changes and update anything wanted.
List<double> Vector;
Vector.Add(0.2);
Vector.Add(0.2);
Vector.Add(0.2);
DoSomething(Vector.GetRange(index,count));
If you need to maintain the original list do this:
public static List<double> GetRange(static List<double> list, int index, int count){
return list.GetRange(Index,Count);
}
public static List<double> DoSomething(static List<double> list){
//do something here
}
Use it like this:
OriginalList().GetRange(Index,Count).DoSomething();
What does GetHashCode() calculate when invoked on the byte[] array?
The 2 data arrays with equal content do not provide the same hash.
Arrays in .NET don't override Equals or GetHashCode, so the value you'll get is basically based on reference equality (i.e. the default implementation in Object) - for value equality you'll need to roll your own code (or find some from a third party). You may want to implement IEqualityComparer<byte[]> if you're trying to use byte arrays as keys in a dictionary etc.
EDIT: Here's a reusable array equality comparer which should be fine so long as the array element handles equality appropriately. Note that you mustn't mutate the array after using it as a key in a dictionary, otherwise you won't be able to find it again - even with the same reference.
using System;
using System.Collections.Generic;
public sealed class ArrayEqualityComparer<T> : IEqualityComparer<T[]>
{
// You could make this a per-instance field with a constructor parameter
private static readonly EqualityComparer<T> elementComparer
= EqualityComparer<T>.Default;
public bool Equals(T[] first, T[] second)
{
if (first == second)
{
return true;
}
if (first == null || second == null)
{
return false;
}
if (first.Length != second.Length)
{
return false;
}
for (int i = 0; i < first.Length; i++)
{
if (!elementComparer.Equals(first[i], second[i]))
{
return false;
}
}
return true;
}
public int GetHashCode(T[] array)
{
unchecked
{
if (array == null)
{
return 0;
}
int hash = 17;
foreach (T element in array)
{
hash = hash * 31 + elementComparer.GetHashCode(element);
}
return hash;
}
}
}
class Test
{
static void Main()
{
byte[] x = { 1, 2, 3 };
byte[] y = { 1, 2, 3 };
byte[] z = { 4, 5, 6 };
var comparer = new ArrayEqualityComparer<byte>();
Console.WriteLine(comparer.GetHashCode(x));
Console.WriteLine(comparer.GetHashCode(y));
Console.WriteLine(comparer.GetHashCode(z));
Console.WriteLine(comparer.Equals(x, y));
Console.WriteLine(comparer.Equals(x, z));
}
}
Like other non-primitive built-in types, it just returns something arbitrary. It definitely doesn't try to hash the contents of the array. See this answer.
Simple solution
public static int GetHashFromBytes(byte[] bytes)
{
return new BigInteger(bytes).GetHashCode();
}
byte[] inherits GetHashCode() from object, it doesn't override it. So what you get is basically object's implementation.
If you are using .NET 6 or at least .NET Core 2.1, you can write less codes and achieve better performance with System.HashCode struct.
Using the method HashCode.AddBytes() which available from .NET 6:
public int GetHashCode(byte[] value)
{
var hash = new HashCode();
hash.AddBytes(value);
return hash.ToHashCode();
}
Using the method HashCode.Add which available from .NET Core 2.1:
public int GetHashCode(byte[] value) =>
value.Aggregate(new HashCode(), (hash, i) => {
hash.Add(i);
return hash;
}).ToHashCode();
Note in the document of HashCode.AddBytes() it says:
This method does not guarantee that the result of adding a span of bytes will match the result of adding the same bytes individually.
In this sharplab demo they are just output same result, but this might be varying from .NET version or runtime environment.
If it's not the same instance, it will return different hashes. I'm guessing it is based on the memory address where it is stored somehow.
I have a struct that looks something like this:
[StructLayout(LayoutKind.Sequential)]
public struct in_addr {
public Anonymous1 S_un;
[StructLayoutAttribute(LayoutKind.Explicit)]
public struct Anonymous1 {
[FieldOffsetAttribute(0)]
public Anonymous2 S_un_b;
[FieldOffsetAttribute(0)]
public Anonymous3 S_un_w;
[FieldOffsetAttribute(0)]
public uint S_addr;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct Anonymous2 {
public byte s_b1;
public byte s_b2;
public byte s_b3;
public byte s_b4;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct Anonymous3 {
public ushort s_w1;
public ushort s_w2;
}
public in_addr(byte[] address) {
S_un.S_addr = (uint)BitConverter.ToInt32(address, 0);
S_un.S_un_b.s_b1 = address[0];
S_un.S_un_b.s_b2 = address[1];
S_un.S_un_b.s_b3 = address[2];
S_un.S_un_b.s_b4 = address[3];
S_un.S_un_w.s_w1 = 0;
S_un.S_un_w.s_w2 = 0;
}
}
When I try to create a new instance of this struct, every byte field is set to 0.
in_addr temp = new in_addr(bytes);
I've stepped through the struct's constructor and verified that the bytes are indeed getting assigned to the fields. But when I step out of the constructor and check the value of temp, everything is 0.
What's causing this?
Because of these lines:
S_un.S_un_w.s_w1 = 0;
S_un.S_un_w.s_w2 = 0;
They are mapped to your 4 bytes via
[FieldOffsetAttribute(0)]
public Anonymous2 S_un_b;
[FieldOffsetAttribute(0)]
public Anonymous3 S_un_w;
I can't reproduce this; your code works for me. I’m using Mono but I very much doubt that this is a bug in the Microsoft C# compiler, it's more likely that you've got an error elsewhere.
I just tested this in VisualStudio 2008 using C# and got the expected output (1, 2).
Try posting the actual example code that you're having an issue with.
EDIT This is why example code can be bad ;)
Your issue was with the StructLayout.Explicit on Anonymous1. Is there a particular reason that
You did explicit instead of sequential and putting them in the order you wanted
You left the indices as 0 for all of them
When I changed it to Sequential and removed the attributes, it worked fine for me.
EDIT 2 (Deleted)
EDIT 3
Your issue is with the assignment in the constructor. Not sure how I missed this. You don't need to set all of those variables, because your FieldOffset attribute makes them all stored in the same location. The struct itself is only occupying 4 bytes of memory (in theory, anyway). Whether you're accessing it via the int, the bytes, or the two shorts, they all go to the same place. As a result, your first two sets of assignments (to the int and to the bytes) are redundant, and the last set (to the shorts setting them to 0) clears out what you just did.
Unfortunately the C# compiler doesn't know this, so I'm sure you added the last assignment because it complained about the struct not being fully assigned. Add the dummy assignments first for the shorts and the int, then assign the bytes explicitly from the array.
If you are using C# 3.0, just try the following:
MyStruct ms = new MyStruct
{
MyByte = 1,
MyNestedStruct.NestedStryctByte = 2
}
That should work, and would alleviate the need to have a constructor in your struct. If you can't directly initialize the NestedStructByte, create it first:
MyStruct ms = new MyStruct
{
MyByte = 1,
MyNestedStruct = new MyStruct.NestedStruct
{
NestedStryctByte = 2
}
}
I tested your code - everything is OK.
public struct MyStruct
{
public byte MyByte;
public NestedStruct MyNestedStruct;
public struct NestedStruct
{
public byte NestedStructByte;
}
public MyStruct(byte[] bytes)
{
MyByte = bytes[0];
MyNestedStruct.NestedStructByte = bytes[1];
}
}
class Program
{
static void Main(string[] args)
{
MyStruct ms = new MyStruct(new byte[] { 1, 2 });
//ms.MyByte; // 0, but should be 1
//ms.MyNestedStruct.NestedStructByte; // 0, but should be 2
}
}