diff --git a/apiCount.include.md b/apiCount.include.md index 1d791631..1b6bbe5a 100644 --- a/apiCount.include.md +++ b/apiCount.include.md @@ -1,28 +1,28 @@ -**API count: 1032** +**API count: 1034** ### Per Target Framework | Target | APIs | | -- | -- | -| `net461` | 974 | -| `net462` | 974 | -| `net47` | 973 | -| `net471` | 972 | -| `net472` | 968 | -| `net48` | 968 | -| `net481` | 968 | -| `netstandard2.0` | 970 | -| `netstandard2.1` | 823 | -| `netcoreapp2.0` | 893 | -| `netcoreapp2.1` | 834 | -| `netcoreapp2.2` | 834 | -| `netcoreapp3.0` | 786 | -| `netcoreapp3.1` | 785 | -| `net5.0` | 657 | -| `net6.0` | 558 | -| `net7.0` | 403 | -| `net8.0` | 284 | -| `net9.0` | 190 | -| `net10.0` | 136 | +| `net461` | 976 | +| `net462` | 976 | +| `net47` | 975 | +| `net471` | 974 | +| `net472` | 970 | +| `net48` | 970 | +| `net481` | 970 | +| `netstandard2.0` | 972 | +| `netstandard2.1` | 825 | +| `netcoreapp2.0` | 895 | +| `netcoreapp2.1` | 836 | +| `netcoreapp2.2` | 836 | +| `netcoreapp3.0` | 788 | +| `netcoreapp3.1` | 787 | +| `net5.0` | 659 | +| `net6.0` | 560 | +| `net7.0` | 405 | +| `net8.0` | 286 | +| `net9.0` | 192 | +| `net10.0` | 138 | | `net11.0` | 58 | -| `uap10.0` | 960 | +| `uap10.0` | 962 | diff --git a/api_list.include.md b/api_list.include.md index 6bf1aa6d..3c1a6ec2 100644 --- a/api_list.include.md +++ b/api_list.include.md @@ -1531,6 +1531,8 @@ #### UnreachableException +#### IUnion + #### StringStream #### ReadOnlyMemoryStream diff --git a/assemblySize.include.md b/assemblySize.include.md index 339ab210..a0a8d92e 100644 --- a/assemblySize.include.md +++ b/assemblySize.include.md @@ -2,51 +2,51 @@ | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| -| netstandard2.0 | 8.0KB | 358.5KB | +350.5KB | +8.0KB | +6.5KB | +8.0KB | +12.5KB | -| netstandard2.1 | 8.5KB | 312.5KB | +304.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | -| net461 | 8.5KB | 357.5KB | +349.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| net462 | 7.0KB | 361.0KB | +354.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| net47 | 7.0KB | 360.5KB | +353.5KB | +9.5KB | +6.5KB | +9.5KB | +14.0KB | -| net471 | 8.5KB | 360.0KB | +351.5KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| net472 | 8.5KB | 358.5KB | +350.0KB | +7.5KB | +6.5KB | +8.0KB | +12.0KB | -| net48 | 8.5KB | 358.5KB | +350.0KB | +7.5KB | +6.5KB | +8.0KB | +12.0KB | -| net481 | 8.5KB | 358.5KB | +350.0KB | +7.5KB | +6.5KB | +8.0KB | +12.0KB | -| netcoreapp2.0 | 9.0KB | 336.0KB | +327.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| netcoreapp2.1 | 9.0KB | 316.0KB | +307.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | -| netcoreapp2.2 | 9.0KB | 316.0KB | +307.0KB | +9.0KB | +6.5KB | +9.5KB | +14.0KB | -| netcoreapp3.0 | 9.5KB | 309.5KB | +300.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| netcoreapp3.1 | 9.5KB | 307.5KB | +298.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | -| net5.0 | 9.5KB | 271.5KB | +262.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | -| net6.0 | 10.0KB | 213.0KB | +203.0KB | +9.5KB | +7.0KB | +512bytes | +3.5KB | -| net7.0 | 10.0KB | 175.0KB | +165.0KB | +11.5KB | +8.0KB | +512bytes | +3.0KB | -| net8.0 | 9.5KB | 145.5KB | +136.0KB | +8.0KB | | +512bytes | +3.0KB | -| net9.0 | 9.5KB | 98.5KB | +89.0KB | +8.5KB | | +512bytes | +3.0KB | -| net10.0 | 10.0KB | 76.0KB | +66.0KB | +8.5KB | | +512bytes | +3.5KB | -| net11.0 | 10.0KB | 20.5KB | +10.5KB | +9.0KB | | +1.0KB | +3.5KB | +| netstandard2.0 | 8.0KB | 359.0KB | +351.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | +| netstandard2.1 | 8.5KB | 313.0KB | +304.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net461 | 8.5KB | 357.5KB | +349.0KB | +8.0KB | +7.0KB | +8.0KB | +12.5KB | +| net462 | 7.0KB | 361.0KB | +354.0KB | +9.5KB | +6.5KB | +9.5KB | +14.0KB | +| net47 | 7.0KB | 361.0KB | +354.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net471 | 8.5KB | 360.0KB | +351.5KB | +7.5KB | +6.5KB | +8.0KB | +12.5KB | +| net472 | 8.5KB | 358.5KB | +350.0KB | +8.0KB | +7.0KB | +8.0KB | +12.5KB | +| net48 | 8.5KB | 358.5KB | +350.0KB | +8.0KB | +7.0KB | +8.0KB | +12.5KB | +| net481 | 8.5KB | 359.0KB | +350.5KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | +| netcoreapp2.0 | 9.0KB | 336.5KB | +327.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| netcoreapp2.1 | 9.0KB | 316.5KB | +307.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| netcoreapp2.2 | 9.0KB | 316.5KB | +307.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| netcoreapp3.0 | 9.5KB | 309.5KB | +300.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | +| netcoreapp3.1 | 9.5KB | 308.0KB | +298.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net5.0 | 9.5KB | 272.0KB | +262.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net6.0 | 10.0KB | 213.0KB | +203.0KB | +10.0KB | +7.0KB | +1.0KB | +3.5KB | +| net7.0 | 10.0KB | 175.0KB | +165.0KB | +12.0KB | +8.5KB | +512bytes | +3.5KB | +| net8.0 | 9.5KB | 145.5KB | +136.0KB | +8.5KB | +512bytes | +512bytes | +3.5KB | +| net9.0 | 9.5KB | 98.5KB | +89.0KB | +8.5KB | | +512bytes | +3.5KB | +| net10.0 | 10.0KB | 76.0KB | +66.0KB | +9.0KB | | +1.0KB | +3.5KB | +| net11.0 | 10.0KB | 21.0KB | +11.0KB | +9.0KB | | +512bytes | +3.5KB | ### Assembly Sizes with EmbedUntrackedSources | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| -| netstandard2.0 | 8.0KB | 525.1KB | +517.1KB | +15.7KB | +8.2KB | +12.9KB | +17.9KB | -| netstandard2.1 | 8.5KB | 452.5KB | +444.0KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | -| net461 | 8.5KB | 525.2KB | +516.7KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| net462 | 7.0KB | 528.7KB | +521.7KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| net47 | 7.0KB | 527.9KB | +520.9KB | +17.2KB | +8.2KB | +14.4KB | +19.4KB | -| net471 | 8.5KB | 527.1KB | +518.6KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| net472 | 8.5KB | 524.5KB | +516.0KB | +15.2KB | +8.2KB | +12.9KB | +17.4KB | -| net48 | 8.5KB | 524.5KB | +516.0KB | +15.2KB | +8.2KB | +12.9KB | +17.4KB | -| net481 | 8.5KB | 524.5KB | +516.0KB | +15.2KB | +8.2KB | +12.9KB | +17.4KB | -| netcoreapp2.0 | 9.0KB | 492.1KB | +483.1KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp2.1 | 9.0KB | 459.7KB | +450.7KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | -| netcoreapp2.2 | 9.0KB | 459.7KB | +450.7KB | +16.7KB | +8.2KB | +14.4KB | +19.4KB | -| netcoreapp3.0 | 9.5KB | 444.3KB | +434.8KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp3.1 | 9.5KB | 442.3KB | +432.8KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | -| net5.0 | 9.5KB | 388.1KB | +378.6KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | -| net6.0 | 10.0KB | 309.4KB | +299.4KB | +17.2KB | +8.7KB | +1.1KB | +4.2KB | -| net7.0 | 10.0KB | 252.6KB | +242.6KB | +19.1KB | +9.4KB | +1.1KB | +3.7KB | -| net8.0 | 9.5KB | 207.6KB | +198.1KB | +15.5KB | +299bytes | +1.1KB | +3.7KB | -| net9.0 | 9.5KB | 139.5KB | +130.0KB | +16.0KB | | +1.1KB | +3.7KB | -| net10.0 | 10.0KB | 108.3KB | +98.3KB | +16.0KB | | +1.1KB | +4.2KB | -| net11.0 | 10.0KB | 30.4KB | +20.4KB | +16.5KB | | +1.6KB | +4.2KB | +| netstandard2.0 | 8.0KB | 526.3KB | +518.3KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | +| netstandard2.1 | 8.5KB | 453.6KB | +445.1KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net461 | 8.5KB | 525.8KB | +517.3KB | +15.7KB | +8.7KB | +12.9KB | +17.9KB | +| net462 | 7.0KB | 529.3KB | +522.3KB | +17.2KB | +8.2KB | +14.4KB | +19.4KB | +| net47 | 7.0KB | 529.1KB | +522.1KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net471 | 8.5KB | 527.7KB | +519.2KB | +15.2KB | +8.2KB | +12.9KB | +17.9KB | +| net472 | 8.5KB | 525.1KB | +516.6KB | +15.7KB | +8.7KB | +12.9KB | +17.9KB | +| net48 | 8.5KB | 525.1KB | +516.6KB | +15.7KB | +8.7KB | +12.9KB | +17.9KB | +| net481 | 8.5KB | 525.6KB | +517.1KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | +| netcoreapp2.0 | 9.0KB | 493.2KB | +484.2KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| netcoreapp2.1 | 9.0KB | 460.9KB | +451.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| netcoreapp2.2 | 9.0KB | 460.9KB | +451.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| netcoreapp3.0 | 9.5KB | 445.0KB | +435.5KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | +| netcoreapp3.1 | 9.5KB | 443.4KB | +433.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net5.0 | 9.5KB | 389.3KB | +379.8KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net6.0 | 10.0KB | 310.1KB | +300.1KB | +17.7KB | +8.7KB | +1.6KB | +4.2KB | +| net7.0 | 10.0KB | 253.2KB | +243.2KB | +19.6KB | +9.9KB | +1.1KB | +4.2KB | +| net8.0 | 9.5KB | 208.2KB | +198.7KB | +16.0KB | +811bytes | +1.1KB | +4.2KB | +| net9.0 | 9.5KB | 140.1KB | +130.6KB | +16.0KB | | +1.1KB | +4.2KB | +| net10.0 | 10.0KB | 108.9KB | +98.9KB | +16.5KB | | +1.6KB | +4.2KB | +| net11.0 | 10.0KB | 30.9KB | +20.9KB | +16.5KB | | +1.1KB | +4.2KB | diff --git a/readme.md b/readme.md index 12efb593..ddf0baec 100644 --- a/readme.md +++ b/readme.md @@ -13,34 +13,34 @@ The package targets `netstandard2.0` and is designed to support the following ru * `uap10` -**API count: 1031** +**API count: 1034** ### Per Target Framework | Target | APIs | | -- | -- | -| `net461` | 973 | -| `net462` | 973 | -| `net47` | 972 | -| `net471` | 971 | -| `net472` | 967 | -| `net48` | 967 | -| `net481` | 967 | -| `netstandard2.0` | 969 | -| `netstandard2.1` | 822 | -| `netcoreapp2.0` | 892 | -| `netcoreapp2.1` | 833 | -| `netcoreapp2.2` | 833 | -| `netcoreapp3.0` | 785 | -| `netcoreapp3.1` | 784 | -| `net5.0` | 656 | -| `net6.0` | 557 | -| `net7.0` | 402 | -| `net8.0` | 283 | -| `net9.0` | 189 | -| `net10.0` | 135 | +| `net461` | 976 | +| `net462` | 976 | +| `net47` | 975 | +| `net471` | 974 | +| `net472` | 970 | +| `net48` | 970 | +| `net481` | 970 | +| `netstandard2.0` | 972 | +| `netstandard2.1` | 825 | +| `netcoreapp2.0` | 895 | +| `netcoreapp2.1` | 836 | +| `netcoreapp2.2` | 836 | +| `netcoreapp3.0` | 788 | +| `netcoreapp3.1` | 787 | +| `net5.0` | 659 | +| `net6.0` | 560 | +| `net7.0` | 405 | +| `net8.0` | 286 | +| `net9.0` | 192 | +| `net10.0` | 138 | | `net11.0` | 58 | -| `uap10.0` | 959 | +| `uap10.0` | 962 | @@ -96,54 +96,54 @@ This project uses features from the newest stable SDK and C# language. As such c | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| -| netstandard2.0 | 8.0KB | 358.5KB | +350.5KB | +8.0KB | +7.0KB | +8.0KB | +12.5KB | -| netstandard2.1 | 8.5KB | 313.0KB | +304.5KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | -| net461 | 8.5KB | 357.5KB | +349.0KB | +7.5KB | +6.5KB | +8.0KB | +12.0KB | -| net462 | 7.0KB | 361.0KB | +354.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| net47 | 7.0KB | 361.0KB | +354.0KB | +9.0KB | +6.0KB | +9.0KB | +13.5KB | -| net471 | 8.5KB | 360.0KB | +351.5KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | -| net472 | 8.5KB | 358.5KB | +350.0KB | +7.5KB | +6.5KB | +8.0KB | +12.5KB | -| net48 | 8.5KB | 358.5KB | +350.0KB | +7.5KB | +6.5KB | +8.0KB | +12.5KB | -| net481 | 8.5KB | 358.5KB | +350.0KB | +8.0KB | +6.5KB | +8.0KB | +12.5KB | -| netcoreapp2.0 | 9.0KB | 336.5KB | +327.5KB | +8.5KB | +6.0KB | +8.5KB | +13.5KB | -| netcoreapp2.1 | 9.0KB | 316.5KB | +307.5KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | +| netstandard2.0 | 8.0KB | 359.0KB | +351.0KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | +| netstandard2.1 | 8.5KB | 313.0KB | +304.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net461 | 8.5KB | 357.5KB | +349.0KB | +8.0KB | +7.0KB | +8.0KB | +12.5KB | +| net462 | 7.0KB | 361.0KB | +354.0KB | +9.5KB | +6.5KB | +9.5KB | +14.0KB | +| net47 | 7.0KB | 361.0KB | +354.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net471 | 8.5KB | 360.0KB | +351.5KB | +7.5KB | +6.5KB | +8.0KB | +12.5KB | +| net472 | 8.5KB | 358.5KB | +350.0KB | +8.0KB | +7.0KB | +8.0KB | +12.5KB | +| net48 | 8.5KB | 358.5KB | +350.0KB | +8.0KB | +7.0KB | +8.0KB | +12.5KB | +| net481 | 8.5KB | 359.0KB | +350.5KB | +7.5KB | +6.5KB | +7.5KB | +12.0KB | +| netcoreapp2.0 | 9.0KB | 336.5KB | +327.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| netcoreapp2.1 | 9.0KB | 316.5KB | +307.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | | netcoreapp2.2 | 9.0KB | 316.5KB | +307.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| netcoreapp3.0 | 9.5KB | 309.5KB | +300.0KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | -| netcoreapp3.1 | 9.5KB | 308.0KB | +298.5KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | -| net5.0 | 9.5KB | 272.0KB | +262.5KB | +8.5KB | +6.5KB | +9.0KB | +13.5KB | -| net6.0 | 10.0KB | 213.0KB | +203.0KB | +10.0KB | +7.0KB | +512bytes | +3.5KB | -| net7.0 | 10.0KB | 175.0KB | +165.0KB | +11.5KB | +8.0KB | +512bytes | +3.0KB | -| net8.0 | 9.5KB | 145.5KB | +136.0KB | +8.5KB | | +512bytes | +3.0KB | +| netcoreapp3.0 | 9.5KB | 309.5KB | +300.0KB | +9.0KB | +6.5KB | +9.0KB | +14.0KB | +| netcoreapp3.1 | 9.5KB | 308.0KB | +298.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net5.0 | 9.5KB | 272.0KB | +262.5KB | +9.0KB | +6.5KB | +9.0KB | +13.5KB | +| net6.0 | 10.0KB | 213.0KB | +203.0KB | +10.0KB | +7.0KB | +1.0KB | +3.5KB | +| net7.0 | 10.0KB | 175.0KB | +165.0KB | +12.0KB | +8.5KB | +512bytes | +3.5KB | +| net8.0 | 9.5KB | 145.5KB | +136.0KB | +8.5KB | +512bytes | +512bytes | +3.5KB | | net9.0 | 9.5KB | 98.5KB | +89.0KB | +8.5KB | | +512bytes | +3.5KB | -| net10.0 | 10.0KB | 76.0KB | +66.0KB | +8.5KB | | +512bytes | +3.5KB | -| net11.0 | 10.0KB | 20.5KB | +10.5KB | +9.0KB | | +1.0KB | +3.5KB | +| net10.0 | 10.0KB | 76.0KB | +66.0KB | +9.0KB | | +1.0KB | +3.5KB | +| net11.0 | 10.0KB | 21.0KB | +11.0KB | +9.0KB | | +512bytes | +3.5KB | ### Assembly Sizes with EmbedUntrackedSources | | Empty Assembly | With Polyfill | Diff | Ensure | ArgumentExceptions | StringInterpolation | Nullability | |----------------|----------------|---------------|-----------|-----------|--------------------|---------------------|-------------| -| netstandard2.0 | 8.0KB | 524.8KB | +516.8KB | +15.7KB | +8.7KB | +12.9KB | +17.9KB | -| netstandard2.1 | 8.5KB | 452.7KB | +444.2KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | -| net461 | 8.5KB | 524.9KB | +516.4KB | +15.2KB | +8.2KB | +12.9KB | +17.4KB | -| net462 | 7.0KB | 528.4KB | +521.4KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| net47 | 7.0KB | 528.1KB | +521.1KB | +16.7KB | +7.7KB | +13.9KB | +18.9KB | -| net471 | 8.5KB | 526.8KB | +518.3KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | -| net472 | 8.5KB | 524.2KB | +515.7KB | +15.2KB | +8.2KB | +12.9KB | +17.9KB | -| net48 | 8.5KB | 524.2KB | +515.7KB | +15.2KB | +8.2KB | +12.9KB | +17.9KB | -| net481 | 8.5KB | 524.2KB | +515.7KB | +15.7KB | +8.2KB | +12.9KB | +17.9KB | -| netcoreapp2.0 | 9.0KB | 492.3KB | +483.3KB | +16.2KB | +7.7KB | +13.4KB | +18.9KB | -| netcoreapp2.1 | 9.0KB | 459.9KB | +450.9KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp2.2 | 9.0KB | 459.9KB | +450.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp3.0 | 9.5KB | 444.0KB | +434.5KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | -| netcoreapp3.1 | 9.5KB | 442.5KB | +433.0KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | -| net5.0 | 9.5KB | 388.3KB | +378.8KB | +16.2KB | +8.2KB | +13.9KB | +18.9KB | -| net6.0 | 10.0KB | 309.1KB | +299.1KB | +17.7KB | +8.7KB | +1.1KB | +4.2KB | -| net7.0 | 10.0KB | 252.3KB | +242.3KB | +19.1KB | +9.4KB | +1.1KB | +3.7KB | -| net8.0 | 9.5KB | 207.3KB | +197.8KB | +16.0KB | +299bytes | +1.1KB | +3.7KB | -| net9.0 | 9.5KB | 139.1KB | +129.6KB | +16.0KB | | +1.1KB | +4.2KB | -| net10.0 | 10.0KB | 108.0KB | +98.0KB | +16.0KB | | +1.1KB | +4.2KB | -| net11.0 | 10.0KB | 30.4KB | +20.4KB | +16.5KB | | +1.6KB | +4.2KB | +| netstandard2.0 | 8.0KB | 526.3KB | +518.3KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | +| netstandard2.1 | 8.5KB | 453.6KB | +445.1KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net461 | 8.5KB | 525.8KB | +517.3KB | +15.7KB | +8.7KB | +12.9KB | +17.9KB | +| net462 | 7.0KB | 529.3KB | +522.3KB | +17.2KB | +8.2KB | +14.4KB | +19.4KB | +| net47 | 7.0KB | 529.1KB | +522.1KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net471 | 8.5KB | 527.7KB | +519.2KB | +15.2KB | +8.2KB | +12.9KB | +17.9KB | +| net472 | 8.5KB | 525.1KB | +516.6KB | +15.7KB | +8.7KB | +12.9KB | +17.9KB | +| net48 | 8.5KB | 525.1KB | +516.6KB | +15.7KB | +8.7KB | +12.9KB | +17.9KB | +| net481 | 8.5KB | 525.6KB | +517.1KB | +15.2KB | +8.2KB | +12.4KB | +17.4KB | +| netcoreapp2.0 | 9.0KB | 493.2KB | +484.2KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| netcoreapp2.1 | 9.0KB | 460.9KB | +451.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| netcoreapp2.2 | 9.0KB | 460.9KB | +451.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| netcoreapp3.0 | 9.5KB | 445.0KB | +435.5KB | +16.7KB | +8.2KB | +13.9KB | +19.4KB | +| netcoreapp3.1 | 9.5KB | 443.4KB | +433.9KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net5.0 | 9.5KB | 389.3KB | +379.8KB | +16.7KB | +8.2KB | +13.9KB | +18.9KB | +| net6.0 | 10.0KB | 310.1KB | +300.1KB | +17.7KB | +8.7KB | +1.6KB | +4.2KB | +| net7.0 | 10.0KB | 253.2KB | +243.2KB | +19.6KB | +9.9KB | +1.1KB | +4.2KB | +| net8.0 | 9.5KB | 208.2KB | +198.7KB | +16.0KB | +811bytes | +1.1KB | +4.2KB | +| net9.0 | 9.5KB | 140.1KB | +130.6KB | +16.0KB | | +1.1KB | +4.2KB | +| net10.0 | 10.0KB | 108.9KB | +98.9KB | +16.5KB | | +1.6KB | +4.2KB | +| net11.0 | 10.0KB | 30.9KB | +20.9KB | +16.5KB | | +1.1KB | +4.2KB | @@ -524,6 +524,90 @@ Reference: [Improvements in native code interop in .NET 5.0](https://devblogs.mi * [DisableRuntimeMarshallingAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.disableruntimemarshallingattribute) +### Unions + +Polyfills the two marker types that the compiler references when emitting [C# 15 union types](https://devblogs.microsoft.com/dotnet/csharp-15-union-types/), so unions can target older runtimes: + + * [UnionAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.unionattribute) + * [IUnion](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.iunion) + +Both types ship in net11. Without them the compiler rejects a `union` declaration with `CS0518` and `CS0656`, so Polyfill supplies them on every earlier target. + +> Polyfill supplies only the `UnionAttribute` and `IUnion` types that the generated union struct references. The `union` keyword itself requires the C# 15 (or later) compiler and cannot be backported to an older compiler. Set `preview` while the feature is in preview. + +> If the consuming project declares its own `UnionAttribute`/`IUnion` in `System.Runtime.CompilerServices` (as preview guidance suggested before these types shipped), delete those declarations. Keeping them results in `CS0101` on earlier targets and `CS0729` on net11. + +Declaring a union: + + + +```cs +record Cat(string Name); + +record Dog(string Name); + +record Bird(string Name); + +union Pet(Cat, Dog, Bird); +``` +snippet source | anchor + + +Consuming a union, using the implicit conversion from a case type and pattern matching to unwrap it: + + + +```cs +public static string Describe(Dog dog) +{ + // implicit conversion from one of the case types + Pet pet = dog; + + // no default arm: the switch is exhaustive because every case type is handled + return pet switch + { + Cat cat => $"cat {cat.Name}", + Dog other => $"dog {other.Name}", + Bird bird => $"bird {bird.Name}" + }; +} +``` +snippet source | anchor + + +The generated union struct implements `IUnion`, so the current value can also be read as an `object`: + + + +```cs +// every union implements IUnion, which exposes the current value as object +public static object? CurrentValue(Pet pet) => + ((IUnion) pet).Value; +``` +snippet source | anchor + + +A union can also be declared explicitly using the polyfilled attribute and interface: + + + +```cs +[Union] +readonly struct IntOrString : IUnion +{ + readonly object? value; + + public IntOrString(int value) => this.value = value; + + public IntOrString(string value) => this.value = value; + + public object? Value => value; +} +``` +snippet source | anchor + + + ## Extensions The class `Polyfill` includes the following extension methods: @@ -2062,6 +2146,8 @@ The class `Polyfill` includes the following extension methods: #### UnreachableException +#### IUnion + #### StringStream #### ReadOnlyMemoryStream @@ -2267,7 +2353,7 @@ void ObjectDisposedExceptionExample(bool isDisposed) ObjectDisposedException.ThrowIf(isDisposed, typeof(Consume)); } ``` -snippet source | anchor +snippet source | anchor @@ -2286,7 +2372,7 @@ void EnsureExample(Order order, Customer customer, string customerId, string ema this.quantity = Ensure.NotNegativeOrZero(quantity); } ``` -snippet source | anchor +snippet source | anchor diff --git a/src/ApiBuilderTests/BuildApiTest.cs b/src/ApiBuilderTests/BuildApiTest.cs index 42fc1098..b5ab6928 100644 --- a/src/ApiBuilderTests/BuildApiTest.cs +++ b/src/ApiBuilderTests/BuildApiTest.cs @@ -24,6 +24,7 @@ public Task RunWithRoslyn() WriteHelper("Utf16", writer, ref count); WriteType(nameof(TaskCompletionSource), writer, ref count); WriteType(nameof(UnreachableException), writer, ref count); + WriteType("IUnion", writer, ref count); WriteType("StringStream", writer, ref count); WriteType("ReadOnlyMemoryStream", writer, ref count); WriteType("WritableMemoryStream", writer, ref count); diff --git a/src/Consume/Consume.cs b/src/Consume/Consume.cs index 868deba1..8e9a5870 100644 --- a/src/Consume/Consume.cs +++ b/src/Consume/Consume.cs @@ -104,6 +104,8 @@ class Consume type = typeof(RequiresUnreferencedCodeAttribute); type = typeof(UnconditionalSuppressMessageAttribute); type = typeof(CompilerFeatureRequiredAttribute); + type = typeof(IUnion); + type = typeof(UnionAttribute); #if FeatureMemory type = typeof(CollectionBuilderAttribute); #endif diff --git a/src/ConsumeCsPreview/Unions.cs b/src/ConsumeCsPreview/Unions.cs new file mode 100644 index 00000000..5d44611c --- /dev/null +++ b/src/ConsumeCsPreview/Unions.cs @@ -0,0 +1,48 @@ +using System.Runtime.CompilerServices; + +namespace ConsumeCsPreview; + +// Compile-only coverage for C# union types. The compiler emits a struct that is +// annotated with UnionAttribute and implements IUnion, so this only compiles +// when both are polyfilled. + +#region UnionDeclaration + +record Cat(string Name); + +record Dog(string Name); + +record Bird(string Name); + +union Pet(Cat, Dog, Bird); + +#endregion + +static class Unions +{ + #region UnionUsage + + public static string Describe(Dog dog) + { + // implicit conversion from one of the case types + Pet pet = dog; + + // no default arm: the switch is exhaustive because every case type is handled + return pet switch + { + Cat cat => $"cat {cat.Name}", + Dog other => $"dog {other.Name}", + Bird bird => $"bird {bird.Name}" + }; + } + + #endregion + + #region UnionValue + + // every union implements IUnion, which exposes the current value as object + public static object? CurrentValue(Pet pet) => + ((IUnion) pet).Value; + + #endregion +} diff --git a/src/Polyfill/IUnion.cs b/src/Polyfill/IUnion.cs new file mode 100644 index 00000000..fbc4dcd7 --- /dev/null +++ b/src/Polyfill/IUnion.cs @@ -0,0 +1,26 @@ +#if !NET11_0_OR_GREATER +#nullable enable + +namespace System.Runtime.CompilerServices; + +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +//Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.iunion?view=net-11.0 +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} + +#else +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.IUnion))] +#endif diff --git a/src/Polyfill/UnionAttribute.cs b/src/Polyfill/UnionAttribute.cs new file mode 100644 index 00000000..aeecb2b5 --- /dev/null +++ b/src/Polyfill/UnionAttribute.cs @@ -0,0 +1,25 @@ +#if !NET11_0_OR_GREATER + +namespace System.Runtime.CompilerServices; + +using Diagnostics; +using Diagnostics.CodeAnalysis; + +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +//Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.unionattribute?view=net-11.0 +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; + +#else +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.UnionAttribute))] +#endif diff --git a/src/Split/net10.0/IUnion.cs b/src/Split/net10.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net10.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net10.0/UnionAttribute.cs b/src/Split/net10.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net10.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net11.0/TypeForwardeds.cs b/src/Split/net11.0/TypeForwardeds.cs index 435914d1..5b038c2e 100644 --- a/src/Split/net11.0/TypeForwardeds.cs +++ b/src/Split/net11.0/TypeForwardeds.cs @@ -20,6 +20,7 @@ [assembly: TypeForwardedTo(typeof(System.Collections.Generic.IAlternateEqualityComparer<,>))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.IsClosedTypeAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.IsExternalInit))] +[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.IUnion))] [assembly: TypeForwardedTo(typeof(System.Collections.Generic.KeyValuePair))] [assembly: TypeForwardedTo(typeof(System.Threading.Lock))] [assembly: TypeForwardedTo(typeof(System.IO.MatchCasing))] @@ -44,6 +45,7 @@ [assembly: TypeForwardedTo(typeof(System.IO.StringStream))] [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.SuppressGCTransitionAttribute))] +[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.UnionAttribute))] [assembly: TypeForwardedTo(typeof(System.IO.UnixFileMode))] [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute))] [assembly: TypeForwardedTo(typeof(System.Diagnostics.UnreachableException))] diff --git a/src/Split/net461/IUnion.cs b/src/Split/net461/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net461/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net461/UnionAttribute.cs b/src/Split/net461/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net461/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net462/IUnion.cs b/src/Split/net462/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net462/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net462/UnionAttribute.cs b/src/Split/net462/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net462/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net47/IUnion.cs b/src/Split/net47/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net47/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net47/UnionAttribute.cs b/src/Split/net47/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net47/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net471/IUnion.cs b/src/Split/net471/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net471/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net471/UnionAttribute.cs b/src/Split/net471/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net471/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net472/IUnion.cs b/src/Split/net472/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net472/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net472/UnionAttribute.cs b/src/Split/net472/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net472/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net48/IUnion.cs b/src/Split/net48/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net48/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net48/UnionAttribute.cs b/src/Split/net48/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net48/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net481/IUnion.cs b/src/Split/net481/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net481/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net481/UnionAttribute.cs b/src/Split/net481/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net481/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net5.0/IUnion.cs b/src/Split/net5.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net5.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net5.0/UnionAttribute.cs b/src/Split/net5.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net5.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net6.0/IUnion.cs b/src/Split/net6.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net6.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net6.0/UnionAttribute.cs b/src/Split/net6.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net6.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net7.0/IUnion.cs b/src/Split/net7.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net7.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net7.0/UnionAttribute.cs b/src/Split/net7.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net7.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net8.0/IUnion.cs b/src/Split/net8.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net8.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net8.0/UnionAttribute.cs b/src/Split/net8.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net8.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/net9.0/IUnion.cs b/src/Split/net9.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/net9.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/net9.0/UnionAttribute.cs b/src/Split/net9.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/net9.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/netcoreapp2.0/IUnion.cs b/src/Split/netcoreapp2.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/netcoreapp2.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/netcoreapp2.0/UnionAttribute.cs b/src/Split/netcoreapp2.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/netcoreapp2.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/netcoreapp2.1/IUnion.cs b/src/Split/netcoreapp2.1/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/netcoreapp2.1/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/netcoreapp2.1/UnionAttribute.cs b/src/Split/netcoreapp2.1/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/netcoreapp2.1/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/netcoreapp2.2/IUnion.cs b/src/Split/netcoreapp2.2/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/netcoreapp2.2/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/netcoreapp2.2/UnionAttribute.cs b/src/Split/netcoreapp2.2/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/netcoreapp2.2/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/netcoreapp3.0/IUnion.cs b/src/Split/netcoreapp3.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/netcoreapp3.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/netcoreapp3.0/UnionAttribute.cs b/src/Split/netcoreapp3.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/netcoreapp3.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/netcoreapp3.1/IUnion.cs b/src/Split/netcoreapp3.1/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/netcoreapp3.1/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/netcoreapp3.1/UnionAttribute.cs b/src/Split/netcoreapp3.1/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/netcoreapp3.1/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/netstandard2.0/IUnion.cs b/src/Split/netstandard2.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/netstandard2.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/netstandard2.0/UnionAttribute.cs b/src/Split/netstandard2.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/netstandard2.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/netstandard2.1/IUnion.cs b/src/Split/netstandard2.1/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/netstandard2.1/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/netstandard2.1/UnionAttribute.cs b/src/Split/netstandard2.1/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/netstandard2.1/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Split/uap10.0/IUnion.cs b/src/Split/uap10.0/IUnion.cs new file mode 100644 index 00000000..1a5691a4 --- /dev/null +++ b/src/Split/uap10.0/IUnion.cs @@ -0,0 +1,20 @@ +// +#pragma warning disable +#nullable enable +namespace System.Runtime.CompilerServices; +/// +/// Provides a common interface for accessing the contents of a union type at runtime. +/// +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +interface IUnion +{ + /// + /// Gets the value contained in the union, or if the union has no value. + /// + object? Value { get; } +} diff --git a/src/Split/uap10.0/UnionAttribute.cs b/src/Split/uap10.0/UnionAttribute.cs new file mode 100644 index 00000000..6f79f10e --- /dev/null +++ b/src/Split/uap10.0/UnionAttribute.cs @@ -0,0 +1,18 @@ +// +#pragma warning disable +namespace System.Runtime.CompilerServices; +using Diagnostics; +using Diagnostics.CodeAnalysis; +/// +/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors. +/// +[ExcludeFromCodeCoverage] +[DebuggerNonUserCode] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] +#if PolyUseEmbeddedAttribute +[global::Microsoft.CodeAnalysis.EmbeddedAttribute] +#endif +#if PolyPublic +public +#endif +sealed class UnionAttribute : Attribute; diff --git a/src/Tests/UnionTests.cs b/src/Tests/UnionTests.cs new file mode 100644 index 00000000..309b8cf9 --- /dev/null +++ b/src/Tests/UnionTests.cs @@ -0,0 +1,67 @@ +using System.Reflection; + +public class UnionTests +{ + [Test] + public async Task IUnion_IsInterfaceExposingObjectValue() + { + var type = typeof(IUnion); + await Assert.That(type.IsInterface).IsTrue(); + + var property = type.GetProperty("Value"); + await Assert.That(property).IsNotNull(); + await Assert.That(property!.PropertyType).IsEqualTo(typeof(object)); + } + + [Test] + public async Task UnionAttribute_HasExpectedShape() + { + var type = typeof(UnionAttribute); + await Assert.That(type.IsSealed).IsTrue(); + await Assert.That(typeof(Attribute).IsAssignableFrom(type)).IsTrue(); + + var usage = type.GetCustomAttribute(); + await Assert.That(usage).IsNotNull(); + await Assert.That(usage!.ValidOn).IsEqualTo(AttributeTargets.Class | AttributeTargets.Struct); + await Assert.That(usage.AllowMultiple).IsFalse(); + await Assert.That(usage.Inherited).IsFalse(); + } + + [Test] + public async Task UserDefinedUnion_ValueRoundTrips() + { + IUnion fromInt = new IntOrString(5); + IUnion fromText = new IntOrString("text"); + + var intValue = fromInt.Value; + var textValue = fromText.Value; + + await Assert.That(intValue).IsEqualTo(5); + await Assert.That(textValue).IsEqualTo("text"); + } + + [Test] + public async Task UserDefinedUnion_IsMarkedAndImplementsIUnion() + { + var type = typeof(IntOrString); + + await Assert.That(type.GetCustomAttribute()).IsNotNull(); + await Assert.That(typeof(IUnion).IsAssignableFrom(type)).IsTrue(); + } + + #region UnionExplicit + + [Union] + readonly struct IntOrString : IUnion + { + readonly object? value; + + public IntOrString(int value) => this.value = value; + + public IntOrString(string value) => this.value = value; + + public object? Value => value; + } + + #endregion +}