diff --git a/src/Microsoft.Windows.CsWin32/templates/DECIMAL.cs b/src/Microsoft.Windows.CsWin32/templates/DECIMAL.cs index cbfa4943..f5b6793d 100644 --- a/src/Microsoft.Windows.CsWin32/templates/DECIMAL.cs +++ b/src/Microsoft.Windows.CsWin32/templates/DECIMAL.cs @@ -1,39 +1,16 @@ internal partial struct DECIMAL { - public DECIMAL(decimal value) + public unsafe DECIMAL(decimal value) { - unchecked - { - const int SignMask = (int)0x80000000; -#if NET5_0_OR_GREATER - Span bits = stackalloc int[4]; - decimal.GetBits(value, bits); -#else - int[] bits = decimal.GetBits(value); -#endif - uint lo32 = (uint)bits[0]; - uint mid32 = (uint)bits[1]; - uint hi32 = (uint)bits[2]; - byte scale = (byte)(bits[3] >> 16); - byte sign = (bits[3] & SignMask) == SignMask ? (byte)0x80 : (byte)0x00; - this.Anonymous2 = new _Anonymous2_e__Union() { Anonymous = new _Anonymous2_e__Union._Anonymous_e__Struct() { Lo32 = lo32, Mid32 = mid32 } }; - this.Hi32 = hi32; - this.Anonymous1 = new _Anonymous1_e__Union() { Anonymous = new _Anonymous1_e__Union._Anonymous_e__Struct() { scale = scale, sign = sign } }; - this.wReserved = 0; - } + // DECIMAL is layout-compatible with decimal. + this = *(DECIMAL*)&value; } - public static implicit operator decimal(DECIMAL value) + public static unsafe implicit operator decimal(DECIMAL value) { - return new decimal( - (int)value.Anonymous2.Anonymous.Lo32, - (int)value.Anonymous2.Anonymous.Mid32, - (int)value.Hi32, - value.Anonymous1.Anonymous.sign == 0x80, - value.Anonymous1.Anonymous.scale); + // DECIMAL is layout-compatible with decimal. + return *(decimal*)&value; } -#if NET5_0_OR_GREATER public static implicit operator DECIMAL(decimal value) => new DECIMAL(value); -#endif } diff --git a/test/GenerationSandbox.Tests/BasicTests.cs b/test/GenerationSandbox.Tests/BasicTests.cs index 0623701a..0d96d441 100644 --- a/test/GenerationSandbox.Tests/BasicTests.cs +++ b/test/GenerationSandbox.Tests/BasicTests.cs @@ -153,11 +153,9 @@ public void DecimalConversion(decimal value) decimal valueRoundTripped = nativeDecimal; Assert.Equal(value, valueRoundTripped); -#if NET5_0_OR_GREATER nativeDecimal = value; valueRoundTripped = nativeDecimal; Assert.Equal(value, valueRoundTripped); -#endif } [Fact] diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs index e5dc0d23..1608b36d 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs @@ -82,6 +82,16 @@ public void SimplestMethod(string tfm) } } + [Fact] + public void DecimalWorksInNet35() + { + this.compilation = this.starterCompilations["net35"]; + this.generator = this.CreateGenerator(); + Assert.True(this.generator.TryGenerate("VarDecDiv", CancellationToken.None)); + this.CollectGeneratedCode(this.generator); + this.AssertNoDiagnostics(); + } + [Fact] public void DbgHelpExternMethodsCanLoadAppLocal() {