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