Re: Getting a byte array from a generic class

Adam Tuliper <[email protected]> Tue, 18 May 2010 12:29:09 -0400
Newsgroups gmane.comp.windows.devel.dotnet.advanced
Message-ID <[email protected]>
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