Skip to content

Commit 14fddb7

Browse files
Andreas LeebAndreas Leeb
authored andcommitted
Improved documentation and debug view
1 parent d79cfb0 commit 14fddb7

File tree

2 files changed

+67
-46
lines changed

2 files changed

+67
-46
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Licensed under MIT No Attribution, see LICENSE file at the root.
2+
// Copyright 2013 Andreas Gullberg Larsen ([email protected]). Maintained at https://github.com/angularsen/UnitsNet.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
7+
namespace UnitsNet.InternalHelpers
8+
{
9+
/// <summary>
10+
/// Utility methods for working with the byte representation of structs.
11+
/// </summary>
12+
internal static class BytesUtility
13+
{
14+
/// <summary>
15+
/// Converts the given <paramref name="value"/> to an array of its underlying bytes.
16+
/// </summary>
17+
/// <typeparam name="T">The struct type.</typeparam>
18+
/// <param name="value">The struct value to convert.</param>
19+
/// <returns>A byte array representing a copy of <paramref name="value"/>s bytes.</returns>
20+
internal static byte[] GetBytes<T>(T value) where T : struct
21+
{
22+
int size = Marshal.SizeOf(value);
23+
byte[] array = new byte[size];
24+
25+
IntPtr ptr = Marshal.AllocHGlobal(size);
26+
27+
try
28+
{
29+
Marshal.StructureToPtr(value, ptr, true);
30+
Marshal.Copy(ptr, array, 0, size);
31+
}
32+
finally
33+
{
34+
Marshal.FreeHGlobal(ptr);
35+
}
36+
37+
return array;
38+
}
39+
}
40+
}

UnitsNet/QuantityValue.cs

Lines changed: 27 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// Licensed under MIT No Attribution, see LICENSE file at the root.
22
// Copyright 2013 Andreas Gullberg Larsen ([email protected]). Maintained at https://github.com/angularsen/UnitsNet.
33

4-
4+
using System;
5+
using System.Diagnostics;
56
using System.Runtime.InteropServices;
7+
using System.Text;
68
using UnitsNet.InternalHelpers;
79

810
namespace UnitsNet
@@ -17,11 +19,15 @@ namespace UnitsNet
1719
/// </list>
1820
/// </summary>
1921
/// <remarks>
20-
/// At the time of this writing, this reduces the number of From(value, unit) overloads to 1/4th:
22+
/// <para>At the time of this writing, this reduces the number of From(value, unit) overloads to 1/4th:
2123
/// From 8 (int, long, double, decimal + each nullable) down to 2 (QuantityValue and QuantityValue?).
22-
/// This also adds more numeric types with no extra overhead, such as float, short and byte.
24+
/// This also adds more numeric types with no extra overhead, such as float, short and byte.</para>
25+
/// <para>So far, the internal representation can be either <see cref="double"/> or <see cref="decimal"/>,
26+
/// but as this struct is realized as a union struct with overlapping fields, only the amount of memory of the largest data type is used.
27+
/// This allows for adding support for smaller data types without increasing the overall size.</para>
2328
/// </remarks>
2429
[StructLayout(LayoutKind.Explicit)]
30+
[DebuggerDisplay("{GetDebugRepresentation()}")]
2531
public readonly struct QuantityValue
2632
{
2733
/// <summary>
@@ -37,7 +43,7 @@ public readonly struct QuantityValue
3743
/// as their value type.
3844
/// </summary>
3945
[FieldOffset(0)]
40-
// bytes layout: 0-1 unused, 2 exponent, 3 sign (only first bit), 4-15 number
46+
// bytes layout: 0-1 unused, 2 exponent, 3 sign (only highest bit), 4-15 number
4147
private readonly decimal _decimalValue;
4248

4349
/// <summary>
@@ -87,7 +93,7 @@ public static explicit operator double(QuantityValue number)
8793
{
8894
UnderlyingDataType.Decimal => (double)number._decimalValue,
8995
UnderlyingDataType.Double => number._doubleValue,
90-
_ => throw new System.NotImplementedException()
96+
_ => throw new NotImplementedException()
9197
};
9298

9399
#endregion
@@ -100,7 +106,7 @@ public static explicit operator decimal(QuantityValue number)
100106
{
101107
UnderlyingDataType.Decimal => number._decimalValue,
102108
UnderlyingDataType.Double => (decimal)number._doubleValue,
103-
_ => throw new System.NotImplementedException()
109+
_ => throw new NotImplementedException()
104110
};
105111

106112
#endregion
@@ -111,56 +117,31 @@ public override string ToString()
111117
{
112118
UnderlyingDataType.Decimal => _decimalValue.ToString(),
113119
UnderlyingDataType.Double => _doubleValue.ToString(),
114-
_ => throw new System.NotImplementedException()
120+
_ => throw new NotImplementedException()
115121
};
116122

123+
private string GetDebugRepresentation()
124+
{
125+
StringBuilder builder = new($"{Type} {ToString()} Hex:");
126+
127+
byte[] bytes = BytesUtility.GetBytes(this);
128+
for (int i = bytes.Length - 1; i >= 0; i--)
129+
{
130+
builder.Append($" {bytes[i]:X2}");
131+
}
132+
133+
return builder.ToString();
134+
}
135+
117136
/// <summary>
118137
/// Describes the underlying type of a <see cref="QuantityValue"/>.
119138
/// </summary>
120139
public enum UnderlyingDataType : byte
121140
{
122-
/// <inheritdoc cref="decimal"/>
123-
/// <remarks>Has to be 0 due to the bit structure of <see cref="decimal"/>.</remarks>
141+
/// <summary><see cref="Decimal"/> must have the value 0 due to the bit structure of <see cref="decimal"/>.</summary>
124142
Decimal = 0,
125143
/// <inheritdoc cref="double"/>
126144
Double = 1
127145
}
128-
129-
#region just for debugging
130-
#if DEBUG
131-
[FieldOffset(0)]
132-
private readonly byte byte0;
133-
[FieldOffset(1)]
134-
private readonly byte byte1;
135-
[FieldOffset(2)]
136-
private readonly byte byte2;
137-
[FieldOffset(3)]
138-
private readonly byte byte3;
139-
[FieldOffset(4)]
140-
private readonly byte byte4;
141-
[FieldOffset(5)]
142-
private readonly byte byte5;
143-
[FieldOffset(6)]
144-
private readonly byte byte6;
145-
[FieldOffset(7)]
146-
private readonly byte byte7;
147-
[FieldOffset(8)]
148-
private readonly byte byte8;
149-
[FieldOffset(9)]
150-
private readonly byte byte9;
151-
[FieldOffset(10)]
152-
private readonly byte byte10;
153-
[FieldOffset(11)]
154-
private readonly byte byte11;
155-
[FieldOffset(12)]
156-
private readonly byte byte12;
157-
[FieldOffset(13)]
158-
private readonly byte byte13;
159-
[FieldOffset(14)]
160-
private readonly byte byte14;
161-
[FieldOffset(15)]
162-
private readonly byte byte15;
163-
#endif
164-
#endregion
165146
}
166147
}

0 commit comments

Comments
 (0)