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