Re: Getting a byte array from a generic class
Adam Tuliper <[email protected]> Tue, 18 May 2010 12:36:18 -0400
| Newsgroups | gmane.comp.windows.devel.dotnet.advanced |
|---|---|
| Message-ID | <[email protected]> |
as per http://msdn.microsoft.com/en-us/library/5s4920fa.aspx
what if you call this on a generic to get sizeof - does that work?
Console.WriteLine("Number of bytes needed by a Point object: {0}",
Marshal.SizeOf(typeof(Point)));
On Tue, May 18, 2010 at 12:29 PM, Adam Tuliper <[email protected]>wrote:
> funny I was seeing if there was a way to get this for a generic and saw
> this posting
>
> http://bytes.com/topic/c-sharp/answers/479712-sizeof-t-c-2-0-generic-classes
> which references this:
> http://msdn.microsoft.com/en-us/library/ms379564
>
> which may be along the lines of what Steve said above.. but with code for a
> GenericBinaryFormatter
>
>
>
> On Tue, May 18, 2010 at 12:25 PM, Eddie Lascu <[email protected]> wrote:
>
>> Actually the method I included below would not compile. This is one that
>> is complete and compiles:
>>
>>
>> /// <summary>
>> /// Get property to obtain a byte stream representation of the
>> value of this NTCIP object
>> /// </summary>
>> public override byte[] ValueAsByteStream
>> {
>> get
>> {
>> // signed integers
>> if (typeof(T) == typeof(SByte))
>> {
>> return BitConverter.GetBytes(Convert.ToSByte(Value));
>> }
>> if (typeof(T) == typeof(Int16))
>> {
>> return BitConverter.GetBytes(Convert.ToInt16(Value));
>> }
>> if (typeof(T) == typeof(Int32))
>> {
>> return BitConverter.GetBytes(Convert.ToInt32(Value));
>> }
>> if (typeof(T) == typeof(Int64))
>> {
>> return BitConverter.GetBytes(Convert.ToInt64(Value));
>> }
>>
>> // unsigned integers
>> if (typeof(T) == typeof(Byte))
>> {
>> return BitConverter.GetBytes(Convert.ToByte(Value));
>> }
>> if (typeof(T) == typeof(UInt16))
>> {
>> return BitConverter.GetBytes(Convert.ToUInt16(Value));
>> }
>> if (typeof(T) == typeof(UInt32))
>> {
>> return BitConverter.GetBytes(Convert.ToUInt32(Value));
>> }
>> if (typeof(T) == typeof(UInt64))
>> {
>> return BitConverter.GetBytes(Convert.ToUInt64(Value));
>> }
>>
>> // float / single
>> if (typeof(T) == typeof(Single))
>> {
>> return BitConverter.GetBytes(Convert.ToSingle(Value));
>> }
>>
>> // double
>> if (typeof(T) == typeof(Double))
>> {
>> return BitConverter.GetBytes(Convert.ToDouble(Value));
>> }
>>
>> // decimal
>> if (typeof(T) == typeof(Decimal))
>> {
>> // WHAT? No BitConverter.GetBytes overload for Decimal?
>> #*$#&B^&(&^^$&^%$$
>> decimal decimalValue = Convert.ToDecimal(Value);
>>
>> byte[] bytes = new byte[16];
>>
>> int[] bits = Decimal.GetBits(decimalValue);
>>
>> int lo = bits[0];
>> int mid = bits[1];
>> int hi = bits[2];
>> int flags = bits[3];
>>
>> bytes[0] = (byte)lo;
>> bytes[1] = (byte)(lo >> 8);
>> bytes[2] = (byte)(lo >> 16);
>> bytes[3] = (byte)(lo >> 24);
>>
>> bytes[4] = (byte)mid;
>> bytes[5] = (byte)(mid >> 8);
>> bytes[6] = (byte)(mid >> 16);
>> bytes[7] = (byte)(mid >> 24);
>>
>> bytes[8] = (byte)hi;
>> bytes[9] = (byte)(hi >> 8);
>> bytes[10] = (byte)(hi >> 16);
>> bytes[11] = (byte)(hi >> 24);
>>
>> bytes[12] = (byte)flags;
>> bytes[13] = (byte)(flags >> 8);
>> bytes[14] = (byte)(flags >> 16);
>> bytes[15] = (byte)(flags >> 24);
>>
>> return bytes;
>> }
>>
>> return null;
>> }
>> }
>>
>> And because BitConverter.GetBytes doesn't have an overload for Decimal, I
>> needed to treat that case separately.
>>
>> Adam, I thought of your suggestion. Problem is that the first line in this
>> sequence doesn't compile:
>>
>> int noOfBytes = sizeof (T);
>>
>> byte[] arrayOfBytes = new byte[noOfBytes];
>>
>> // copy byte-by-byte in a few lines of unsafe code
>>
>> You can't take sizeof of a managed type and despite the fact that the
>> class declaration has a constraint to type T to be a struct, further down
>> this piece of information is lost and the compiler will cry foul.
>>
>> Thanks,
>> Eddie
>>
>>
>> -----Original Message-----
>> From: Discussion of advanced .NET topics. [mailto:
>> [email protected]] On Behalf Of Adam Tuliper
>> Sent: Tuesday, May 18, 2010 12:04 PM
>> To: [email protected]
>> Subject: Re: [ADVANCED-DOTNET] Getting a byte array from a generic class
>>
>> you could also I believe use sizeof and unsafe code to do this manual
>> conversion.. otherwise what you have is appropriate considering the few
>> types to check.
>>
>> now.. if someone can indeed come up with something better hats off to them
>> :
>> )
>>
>>
>>
>>
>> On Tue, May 18, 2010 at 10:54 AM, Eddie Lascu <[email protected]>
>> wrote:
>>
>> > Hi there,
>> >
>> > I need to pick your brains with regard to a more elegant solution to a
>> > problem I'm dealing with right now. I have a generic class that wraps
>> any
>> > type of numeric values (short, int, decimal, double or float). Removing
>> the
>> > parts that are not interesting, this class is something like this:
>> >
>> > public abstract class NumericNtcipObject<T> where T : struct,
>> > IComparable<T>
>> > {
>> > protected NumericNtcipObject(T value)
>> > {
>> > double val;
>> > Debugging.Assert(typeof(T).IsValueType &&
>> > typeof(T).IsPrimitive);
>> > Debugging.Assert(double.TryParse(value.ToString(), out val));
>> >
>> > Value = value;
>> > }
>> >
>> > public T Value
>> > {
>> > set
>> > {
>> > _value = value;
>> > }
>> > }
>> >
>> > public byte[] ValueAsByteStream
>> > {
>> > get
>> > {
>> > // Need help here
>> > }
>> > }
>> >
>> > protected T _value;
>> > }
>> >
>> > The class will be derived from and will only be instantiated with
>> numeric
>> > values. I want to create a property that can give me a byte array
>> containing
>> > all the bytes of the underlying value. If this would not be a generic
>> class,
>> > I could do:
>> >
>> > return BitConverter.GetBytes(Value);
>> >
>> > Unfortunately, BitConverter.GetBytes cannot resolve the type of Value so
>> > this solution goes out the window. I need the exact number of bytes, so
>> > casting to a type with a larger range is not good.
>> >
>> > I can do something like this:
>> >
>> >
>> > public byte[] ValueAsByteStream
>> > {
>> > get
>> > {
>> > if(typeof(T) == typeof(Int16))
>> > {
>> > return BitConverter.GetBytes(Value.ToInt16(new
>> > NumberFormatInfo()));
>> > }
>> >
>> > if (typeof(T) == typeof(Int32))
>> > {
>> > return BitConverter.GetBytes(Value.ToInt32(new
>> > NumberFormatInfo()));
>> > }
>> >
>> > if (typeof(T) == typeof(Int64))
>> > {
>> > return BitConverter.GetBytes(Value.ToInt64(new
>> > NumberFormatInfo()));
>> > }
>> >
>> > if (typeof(T) == typeof(UInt16))
>> > {
>> > return BitConverter.GetBytes(Value.ToUInt16(new
>> > NumberFormatInfo()));
>> > }
>> >
>> > if (typeof(T) == typeof(UInt32))
>> > {
>> > return BitConverter.GetBytes(Value.ToUInt32(new
>> > NumberFormatInfo()));
>> > }
>> >
>> > if (typeof(T) == typeof(UInt64))
>> > {
>> > return BitConverter.GetBytes(Value.ToUInt64(new
>> > NumberFormatInfo()));
>> > }
>> > // rest of types here
>> >
>> > return null;
>> > }
>> > }
>> >
>> > but this is not very nice.
>> >
>> > Can either of you smart guys give me a brilliant idea here?
>> >
>> > Thanks in advance,
>> > Eddie
>> >
>> > ===================================
>> > View archives and manage your subscription(s) at
>> > http://peach.ease.lsoft.com/archives
>> >
>>
>> ===================================
>> View archives and manage your subscription(s) at
>> http://peach.ease.lsoft.com/archives
>>
>> ===================================
>> View archives and manage your subscription(s) at
>> http://peach.ease.lsoft.com/archives
>>
>
>
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives