Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Microsoft.Toolkit.HighPerformance package #3128

Merged
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
319 commits
Select commit Hold shift + click to select a range
fc9ead5
Code refactoring
Sergio0694 Feb 15, 2020
9f9be38
Added StringExtensions tests
Sergio0694 Feb 15, 2020
79cb412
Fixed test method names
Sergio0694 Feb 15, 2020
bdf712e
Added ArrayExtensions tests
Sergio0694 Feb 15, 2020
f47b006
Removed MemoryPool<T>.Resize extension
Sergio0694 Feb 15, 2020
445f221
Added ArrayPoolExtensions tests
Sergio0694 Feb 15, 2020
6c76b1c
Added SpinLockExtensions tests
Sergio0694 Feb 15, 2020
9c877dd
Moved HashCode<T> class to Helpers namespace
Sergio0694 Feb 15, 2020
c81104c
Added ByReference<T> tests
Sergio0694 Feb 15, 2020
27f8a01
Changed visibility of one constructor
Sergio0694 Feb 15, 2020
c7edb06
Improved ByReference<T> tests
Sergio0694 Feb 15, 2020
515913b
Added ReadOnlyByReference<T> tests
Sergio0694 Feb 15, 2020
6569e50
Merge pull request #2 from Sergio0694/tests/high-perf-apis
Sergio0694 Feb 15, 2020
24e74ca
Fixed a small build error
Sergio0694 Feb 15, 2020
54e04ef
Added new List<T> extensions
Sergio0694 Feb 15, 2020
092057a
Added List<T> extensions tests
Sergio0694 Feb 15, 2020
2306037
Merge pull request #3 from Sergio0694/feature/high-perf-list-extensions
Sergio0694 Feb 15, 2020
8b01680
Fixed a parameter name
Sergio0694 Feb 15, 2020
7b713c3
Fixed incorrect XML docs
Sergio0694 Feb 15, 2020
a50d0dd
Added missing List<T> extension APIs
Sergio0694 Feb 15, 2020
7337a74
Disabled warning
Sergio0694 Feb 15, 2020
1c8b34f
Removed unnecessary type constraint
Sergio0694 Feb 15, 2020
41c64bf
Bug fixes to some List<T> extensions
Sergio0694 Feb 15, 2020
0318498
Improved some XML docs
Sergio0694 Feb 15, 2020
4ded3cf
Added List<T>.DangerousAsSpan extension
Sergio0694 Feb 15, 2020
124d081
Added more unit tests
Sergio0694 Feb 15, 2020
9af1541
Fixed a bug in the List<T>.DangerousAsSpan extension
Sergio0694 Feb 15, 2020
637b772
Minor tweaks to some docs
Sergio0694 Feb 15, 2020
d7d33e4
Removed List<T> extensions (too hacky)
Sergio0694 Feb 16, 2020
22751f0
Minor code tweaks (just in case)
Sergio0694 Feb 16, 2020
b0c364d
Fixed incorrect API visibility
Sergio0694 Feb 16, 2020
7337fa2
Added tests for the HashCode<T> type
Sergio0694 Feb 16, 2020
59a0b0f
Added .NET Core 3.0 tests for HashCode<T>
Sergio0694 Feb 16, 2020
731131c
Added ParallelHelper.For tests
Sergio0694 Feb 16, 2020
177ec09
Code refactoring
Sergio0694 Feb 16, 2020
768f29b
Added ParallelHelper.For2D tests
Sergio0694 Feb 16, 2020
ad6d647
Fixed empty condition check for 2D loops
Sergio0694 Feb 16, 2020
0aeb839
Added ParallelHelper.ForEach in tests
Sergio0694 Feb 16, 2020
0a15b25
Added ParallelHelper.ForEach ref tests
Sergio0694 Feb 16, 2020
78376cf
Fixed ParallelHelper.For2D tests
Sergio0694 Feb 17, 2020
2e5dc71
Improved ParallelHelper.For/2D tests
Sergio0694 Feb 17, 2020
e52333d
Switched HighPerformance tests to shared project
Sergio0694 Feb 17, 2020
25bfeef
Renamed HighPerformance.NetCore project
Sergio0694 Feb 17, 2020
0bc4710
Moved HighPerformance tests to subfolder
Sergio0694 Feb 17, 2020
198f021
Fixed incorrect namespaces
Sergio0694 Feb 17, 2020
0cc1bad
Added empty HighPerformance.UWP test project
Sergio0694 Feb 17, 2020
98f22ef
Fixed shared project for UWP test project
Sergio0694 Feb 17, 2020
d3d2c6a
Added missing Unsafe NuGet package to UWP project
Sergio0694 Feb 17, 2020
a8163ee
Switched compile tile directives in HighPerformance project
Sergio0694 Feb 17, 2020
f4fb15a
Merge pull request #4 from Sergio0694/tests/high-perf-on-uwp
Sergio0694 Feb 17, 2020
0d0fa11
Added missing file headers
Sergio0694 Feb 17, 2020
481989f
Minor code refactoring to HashCode<T>
Sergio0694 Feb 19, 2020
1fbb18a
Minor performance improvements
Sergio0694 Feb 19, 2020
fac4974
Fixed HashCode<T>.Combine API for > int.MaxValue byte sizes
Sergio0694 Feb 19, 2020
b3e1b6c
Improved HashCode<T>.Combine performance on small spans
Sergio0694 Feb 19, 2020
e8f667f
Speed improvements in the GetDjb2HashCode<T> API
Sergio0694 Feb 19, 2020
fd015c2
Refactored HashCode<T> to facilitate extensions
Sergio0694 Feb 20, 2020
b4e0228
Fixed incorrect namespace
Sergio0694 Feb 20, 2020
3e9e562
Added HashCodeExtensions class
Sergio0694 Feb 20, 2020
fe69083
Added HashCodeExtensions tests
Sergio0694 Feb 20, 2020
51d1f03
Merge pull request #5 from Sergio0694/feature/hash-code-extensions
Sergio0694 Feb 20, 2020
d9e89a6
Minor code style tweaks
Sergio0694 Feb 20, 2020
fd5eab5
Added SpanEnumerable<T> type
Sergio0694 Feb 21, 2020
6c13389
Updated T[] and Span<T> Enumerate extensions
Sergio0694 Feb 21, 2020
e03c05c
Added SpanExtensions tests
Sergio0694 Feb 21, 2020
8160b97
Merge pull request #6 from Sergio0694/feature/span-enumerator
Sergio0694 Feb 21, 2020
5825f7c
Fixed an issue in the DJB2 hash method
Sergio0694 Feb 22, 2020
d0604e4
Minor code refactoring
Sergio0694 Feb 22, 2020
d779651
Added EditorBrowsable attributes to enumerator types
Sergio0694 Feb 22, 2020
c6a62e8
Added MemoryOwner<T> type
Sergio0694 Feb 23, 2020
dcea9d2
Minor code refactoring
Sergio0694 Feb 23, 2020
1d13037
More code refactoring
Sergio0694 Feb 23, 2020
a0cac52
Added MemoryOwner<T> Empty and Length properties
Sergio0694 Feb 23, 2020
0170a85
Added missing header text
Sergio0694 Feb 23, 2020
4d68280
Fixed a refactoring typo
Sergio0694 Feb 23, 2020
61a96e1
Added MemoryOwner<T> tests
Sergio0694 Feb 23, 2020
49cdcde
Minor code refactoring
Sergio0694 Feb 23, 2020
ebc9de1
Fixed MemoryOwner<T> XML docs
Sergio0694 Mar 3, 2020
8246a62
Minor optimization to GetDjb2HashCode
Sergio0694 Mar 3, 2020
fd0dd18
Minor optimization to HashCode<T>.CombineValues
Sergio0694 Mar 3, 2020
bd8e98d
Minor optimization to Count extension with managed types
Sergio0694 Mar 3, 2020
a8b7f9e
Added a Count test for the managed path
Sergio0694 Mar 3, 2020
a128948
Added BoolExtensions.ToInt API
Sergio0694 Mar 5, 2020
9a21816
Removed automatically added rules
Sergio0694 Mar 8, 2020
9e9bb1b
Fixed incorrect XML docs
Sergio0694 Mar 8, 2020
50ab934
Added MemoryOwner<T>.DangerousGetReference API
Sergio0694 Mar 8, 2020
a9b6fe4
Added extensions for some MemoryMarshal APIs
Sergio0694 Mar 9, 2020
3151b83
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 9, 2020
4ac25b8
Minor code tweaks
Sergio0694 Mar 9, 2020
c68c000
Added MemoryOwner<T> method
Sergio0694 Mar 9, 2020
1361e6a
Added more XML comments
Sergio0694 Mar 9, 2020
f8b2d47
Fixed an incorrect method prototype
Sergio0694 Mar 9, 2020
89a2433
Code refactoring, added AllocationMode enum
Sergio0694 Mar 10, 2020
adf1cf7
Added SpanOwner<T> type
Sergio0694 Mar 10, 2020
0ce5444
Added SpanOwner<T> tests
Sergio0694 Mar 10, 2020
53ac1ef
Removed unnecessary check
Sergio0694 Mar 10, 2020
de1e761
Removed unnecessary package reference on .NET Standard 2.1
Sergio0694 Mar 10, 2020
19db944
Improved tests for ReadOnlySpan<T>.Count
Sergio0694 Mar 11, 2020
aa15f3c
Fixed a bug in ReadOnlySpan<T>.Count with managed types
Sergio0694 Mar 11, 2020
2d0b7dd
Updated two type constraints
Sergio0694 Mar 12, 2020
3a8aeb8
Minor optimizations to ParallelHelper
Sergio0694 Mar 12, 2020
ec5cbd0
Minor code tweaks
Sergio0694 Mar 12, 2020
4246fcd
Removed unnecessary APIs
Sergio0694 Mar 12, 2020
5a8d245
Added UInt32Extensions class
Sergio0694 Mar 12, 2020
2496665
Added unit tests for the UInt32Extensions class
Sergio0694 Mar 12, 2020
9a87296
Fixed some comments
Sergio0694 Mar 12, 2020
66d430c
Added some remarks to the new uint APIs
Sergio0694 Mar 12, 2020
e161a94
Minor optimization
Sergio0694 Mar 12, 2020
9c1a1b3
Added UInt64Extensions class
Sergio0694 Mar 12, 2020
c7ef640
Added unit tests for UInt64Extensions type
Sergio0694 Mar 12, 2020
6e9a2a1
Fixed some typos and comments
Sergio0694 Mar 12, 2020
2952daf
Fixed a unit test
Sergio0694 Mar 12, 2020
2a6335b
Minor performance improvements
Sergio0694 Mar 12, 2020
28d10c7
Added ToString() override and debug display to MemoryOwner<T>
Sergio0694 Mar 13, 2020
bc8094c
Added ToString() override and debug display to SpanOwner<T>
Sergio0694 Mar 13, 2020
e7e066d
Added MemoryOwner<T> debug proxy type
Sergio0694 Mar 13, 2020
0e40898
Added SpanOwner<T> debug proxy type
Sergio0694 Mar 13, 2020
321864e
Added missing using directive
Sergio0694 Mar 13, 2020
096ac2c
Added info to the .csproj file
Sergio0694 Mar 13, 2020
bdaa7ee
Removed two APIs, for additional safety
Sergio0694 Mar 13, 2020
7846747
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 13, 2020
dc1a502
Refactored bit helpers into a separate class, added by ref overloads
Sergio0694 Mar 14, 2020
2df5324
Minor code tweaks
Sergio0694 Mar 14, 2020
3d224a5
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 15, 2020
a477fd1
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 18, 2020
90d993c
Added Box<T> type
Sergio0694 Mar 18, 2020
9a0e77f
Added tests for the Box<T> type
Sergio0694 Mar 18, 2020
cc8f52e
Merge pull request #11 from Sergio0694/feature/box-T
Sergio0694 Mar 18, 2020
dd6eb33
Added Box<T> object schema
Sergio0694 Mar 18, 2020
fd5b7da
Added Box<T>.GetFrom(object) API
Sergio0694 Mar 19, 2020
ce87e47
Added more Box<T> tests, added more comments
Sergio0694 Mar 19, 2020
ae09fbd
Fixed a copy paste fail
Sergio0694 Mar 19, 2020
69494f2
Added ValueTypeExtensions type
Sergio0694 Mar 19, 2020
b406e94
Added ValueTypeExtensions tests
Sergio0694 Mar 19, 2020
e7c767e
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 19, 2020
6035a0f
Added missing GC.SuppressFinalize call in MemoryOwner<T>
Sergio0694 Mar 20, 2020
6a486b8
Initial implementation of MemoryStream
Sergio0694 Mar 20, 2020
345d375
Implemented MemoryStream.Seek method
Sergio0694 Mar 20, 2020
b0c4f97
Implemented ReadByte and WriteByte methods
Sergio0694 Mar 20, 2020
f8102ef
Added Memory<T> extension to create a Stream
Sergio0694 Mar 20, 2020
c3a0c2c
Implemented MemoryStream.Dispose method
Sergio0694 Mar 20, 2020
935572c
Fixed typos in a test class
Sergio0694 Mar 20, 2020
2c48a16
Added ReadAsync overrides
Sergio0694 Mar 22, 2020
8b8e3c7
Added WriteAsync overrides
Sergio0694 Mar 22, 2020
faa6f77
Code refactoring
Sergio0694 Mar 22, 2020
8f99d1e
Added more .NET Standard 2.1 overrides
Sergio0694 Mar 22, 2020
fc9fea7
Moved CopyToAsync method to .NET Standard 2.0
Sergio0694 Mar 22, 2020
50f4cdc
Moved FlushAsync, reordered methods
Sergio0694 Mar 22, 2020
627efc6
Added [ReadOnly]Memory<T> extension tests
Sergio0694 Mar 22, 2020
56752f0
Added initial stream tests
Sergio0694 Mar 22, 2020
ddc2479
Fixed a bug in MemoryStream.Read
Sergio0694 Mar 23, 2020
5edaebb
Added unit tests for the MemoryStream type
Sergio0694 Mar 23, 2020
e37961c
Added MemoryStream.[Read|Write]Byte tests, minor tweaks
Sergio0694 Mar 23, 2020
cca83a0
Merge pull request #12 from Sergio0694/feature/memory-streams
Sergio0694 Mar 23, 2020
66ae978
Updated .sln file
Sergio0694 Mar 23, 2020
059f0c8
Added IMemoryOwnerStream type
Sergio0694 Mar 23, 2020
7e3d812
Added IMemoryOwnerExtensions.AsStream type
Sergio0694 Mar 23, 2020
b6082e2
Minor tweaks to some XML comments
Sergio0694 Mar 23, 2020
30d8b16
Added IMemoryOwner extensions and stream tests
Sergio0694 Mar 23, 2020
f8e29d8
Fixed an incorrect namespace
Sergio0694 Mar 23, 2020
9327fcd
Aadded ArrayPoolBufferWriter<T> type
Sergio0694 Mar 23, 2020
93b9081
Minor code refactoring
Sergio0694 Mar 23, 2020
7cb64b3
Added debug view and ToString override for ArrayPoolBufferWriter<T>
Sergio0694 Mar 23, 2020
f134100
Minor code refactoring
Sergio0694 Mar 23, 2020
9acf1c9
Added destructor to ArrayPoolBufferWriter<T> type
Sergio0694 Mar 23, 2020
c51ff5a
Added tests for ArrayPoolBufferWriter<T>
Sergio0694 Mar 23, 2020
ef4c0de
Merge pull request #13 from Sergio0694/feature/pool-buffer-writer
Sergio0694 Mar 23, 2020
9dd5a43
Fixed some copy-paste fails
Sergio0694 Mar 23, 2020
14c025a
Added IMemoryOwner<T> interface to ArrayPoolBufferWriter<T>
Sergio0694 Mar 23, 2020
96845ba
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 23, 2020
0d38b2b
Updated .csproj description
Sergio0694 Mar 23, 2020
be2a3f6
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 24, 2020
648a373
Fixed some comments
Sergio0694 Mar 25, 2020
773bfe3
Merge branch 'master' into feature/high-perf-apis
michael-hawker Mar 25, 2020
2b6ff44
Updated sln
azchohfi Mar 25, 2020
a51f3b2
Minor code style tweak
Sergio0694 Mar 25, 2020
989d621
Minor optimization, code style tweaks
Sergio0694 Mar 25, 2020
cb67314
Fixed some tests not running on .NET Core 3.0
Sergio0694 Mar 25, 2020
d1b84e1
Added initial Array2DExtensions type
Sergio0694 Mar 25, 2020
10d3d1d
Added T[,].AsSpan extension
Sergio0694 Mar 25, 2020
81298f9
Added Count<T> and Djb2 hashcode extensions for T[,] arrays
Sergio0694 Mar 25, 2020
54bde92
Added tests for the 2D array extensions
Sergio0694 Mar 25, 2020
cff0954
Code refactoring
Sergio0694 Mar 25, 2020
32ea59b
Added NullableByReference<T> type
Sergio0694 Mar 25, 2020
be57346
Minor code refactoring
Sergio0694 Mar 25, 2020
d538383
Added NullableReadOnlyByReference<T> type
Sergio0694 Mar 25, 2020
e3855f2
Added unit tests for new Nullable[ReadOnly]ByReference<T> types
Sergio0694 Mar 25, 2020
750df08
Merge pull request #16 from Sergio0694/feature/nullable-by-ref
Sergio0694 Mar 25, 2020
d4d4e39
Fixed an XML comment
Sergio0694 Mar 25, 2020
a076be0
Added T[,] array GetRow and GetColumn extensions
Sergio0694 Mar 25, 2020
95edf1d
Added Array2DColumnEnumerable<T>.ToArray() helper method
Sergio0694 Mar 25, 2020
79494f4
Code refactoring
Sergio0694 Mar 25, 2020
27f3cea
Added T[,].GetRow support on .NET Standard 2.0
Sergio0694 Mar 25, 2020
160b753
Added and optimized T[,].Fill extension
Sergio0694 Mar 25, 2020
eca873c
Added T[,].Fill tests
Sergio0694 Mar 25, 2020
41b2ea8
Added tests for T[,].GetRow extension
Sergio0694 Mar 25, 2020
acbb53e
Bug fixes in the 2D array enumerators
Sergio0694 Mar 25, 2020
536ceec
Added tests for T[,].GetColumn extension
Sergio0694 Mar 25, 2020
ad58d1d
Merge pull request #17 from Sergio0694/feature/toolkit-api-port
Sergio0694 Mar 25, 2020
c02a3ab
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 26, 2020
0abbe26
Fixed a typo
Sergio0694 Mar 26, 2020
b26ef88
Fixed duplicate using directives
Sergio0694 Mar 26, 2020
b918082
Fixed an XML comment
Sergio0694 Mar 26, 2020
4b053aa
Inverted precompiler conditional directive for clarity
Sergio0694 Mar 26, 2020
d61d6bd
Fixed error in an XML comment
Sergio0694 Mar 26, 2020
fd6043b
Removed unnecessary using directive
Sergio0694 Mar 26, 2020
760fcd2
Fixed publisher name in UWP test project
Sergio0694 Mar 26, 2020
e3ee8a8
Added StyleCop.Analyzers package to UWP test project
Sergio0694 Mar 26, 2020
dcd9bba
Resolved StyleCop warnings in unit tests
Sergio0694 Mar 26, 2020
2fd6342
Added StyleCop.Analyzers package to .NET Core test project
Sergio0694 Mar 26, 2020
e747688
Resolved .NET Core specific StyleCop warnings
Sergio0694 Mar 26, 2020
570b083
Updated Test SDK and packages in .NET Core unit test project
Sergio0694 Mar 26, 2020
31c27e6
Fixed object name in MemoryStream.ThrowObjectDisposedException()
Sergio0694 Mar 26, 2020
f1cf183
Minor code style tweak and optimization
Sergio0694 Mar 26, 2020
2ff55e1
Added test for the argument name in ParallelHelper exceptions
Sergio0694 Mar 26, 2020
af44306
Fixed visibility modifiers
Sergio0694 Mar 26, 2020
487808a
Fixed Box<T> type on ARM devices
Sergio0694 Mar 26, 2020
8774bc7
Added MemoryStream tests for argument names in exceptions
Sergio0694 Mar 27, 2020
939e6ee
Minor improvements to some unit tests
Sergio0694 Mar 27, 2020
6ab2a4f
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Mar 27, 2020
692d0cf
Removed duplicate System.Runtime.CompilerServices.Unsafe reference
Sergio0694 Mar 27, 2020
abf4beb
Removed unnecessary StyleCop reference and .ruleset file
Sergio0694 Mar 27, 2020
f2b4977
Resolved StyleCop warnings in unit tests
Sergio0694 Mar 27, 2020
5ccbc13
Minor performance improvements in ByReference<T> types on x64
Sergio0694 Mar 27, 2020
a18b783
Minor style tweaks
Sergio0694 Mar 27, 2020
7b0ec84
Fixed missed refactoring
Sergio0694 Mar 27, 2020
f86d948
Code refactoring
Sergio0694 Mar 28, 2020
3ac3338
Added missing readonly struct modifiers
Sergio0694 Mar 31, 2020
fd22cc1
Merge branch 'master' into feature/high-perf-apis
azchohfi Apr 1, 2020
f3826c3
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Apr 1, 2020
1a34ded
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Apr 1, 2020
b59948c
Enabgled running HighPerformance tests on build.
azchohfi Apr 2, 2020
9382830
Bug fixes in the Box<T> type on some runtimes
Sergio0694 Apr 2, 2020
a9e6b15
Added missing "Pack" target in UWP test project
Sergio0694 Apr 2, 2020
f63eb02
Code refactoring, moved Box<T> extensions to same file for clarity
Sergio0694 Apr 2, 2020
fe40cfb
Merge branch 'master' into feature/high-perf-apis
azchohfi Apr 2, 2020
cfd67b4
Merge branch 'master' into feature/high-perf-apis
azchohfi Apr 2, 2020
debdac5
Bumped System.Runtime.CompilerServices.Unsafe to 5.0.0-preview.2.20160.6
Sergio0694 Apr 2, 2020
77ad2fb
Fixed Box<T>.ToString/GetHashCode issues on .NET Core 2.1 Release
Sergio0694 Apr 2, 2020
b8654de
Updated comments on the Box<T>.GetReference() method
Sergio0694 Apr 2, 2020
6b9ab8e
Fixed package downgrade in UWP test project
Sergio0694 Apr 2, 2020
41af423
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Apr 10, 2020
c1d01e1
Aligned ref returns for ReadOnlySpan<T>/string to MemoryMarsha.GetRef…
Sergio0694 Apr 11, 2020
14d09bb
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Apr 19, 2020
da2d1db
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Apr 22, 2020
d31f63d
Merge branch 'master' into feature/high-perf-apis
Sergio0694 Apr 23, 2020
893d0e8
Merge branch 'master' into feature/high-perf-apis
Sergio0694 May 5, 2020
b996bb3
Merge branch 'master' into feature/high-perf-apis
Sergio0694 May 5, 2020
d4344f4
Renamed ByReference<T> APIs
Sergio0694 May 5, 2020
80d71ac
Removed unnecessary preview package
Sergio0694 May 5, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
219 changes: 219 additions & 0 deletions Microsoft.Toolkit.HighPerformance/Box{T}.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;

#nullable enable

namespace Microsoft.Toolkit.HighPerformance
{
/// <summary>
/// A <see langword="class"/> that represents a boxed <typeparamref name="T"/> value on the managed heap.
/// </summary>
/// <typeparam name="T">The type of value being boxed.</typeparam>
[DebuggerDisplay("{ToString(),raw}")]
public sealed class Box<T>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have some examples/docs at least inline here if not called out about why/where this could be used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 018f4a7.

where T : struct
{
// Boxed value types in the CLR are represented in memory as simple objects that store the method table of
// the corresponding T value type being boxed, and then the data of the value being boxed:
// [ sync block || pMethodTable || boxed T value ]
// ^ ^
// | \-- Unsafe.Unbox<T>(Box<T>)
// \-- Box<T> reference
// For more info, see: https://mattwarren.org/2017/08/02/A-look-at-the-internals-of-boxing-in-the-CLR/.
// Note that there might be some padding before the actual data representing the boxed value,
// which might depend on both the runtime and the exact CPU architecture.
// This is automatically handled by the unbox !!T instruction in IL, which
// unboxes a given value type T and returns a reference to its boxed data.

/// <summary>
/// Initializes a new instance of the <see cref="Box{T}"/> class.
/// </summary>
/// <remarks>
/// This constructor is never used, it is only declared in order to mark it with
/// the <see langword="private"/> visibility modifier and prevent direct use.
/// </remarks>
private Box()
{
}

/// <summary>
/// Returns a <see cref="Box{T}"/> reference from the input <see cref="object"/> instance.
/// </summary>
/// <param name="obj">The input <see cref="object"/> instance, representing a boxed <typeparamref name="T"/> value.</param>
/// <returns>A <see cref="Box{T}"/> reference pointing to <paramref name="obj"/>.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Box<T> GetFrom(object obj)
{
if (obj.GetType() != typeof(T))
{
ThrowInvalidCastExceptionForGetFrom();
}

return Unsafe.As<Box<T>>(obj);
}

/// <summary>
/// Returns a <see cref="Box{T}"/> reference from the input <see cref="object"/> instance.
/// </summary>
/// <param name="obj">The input <see cref="object"/> instance, representing a boxed <typeparamref name="T"/> value.</param>
/// <returns>A <see cref="Box{T}"/> reference pointing to <paramref name="obj"/>.</returns>
/// <remarks>
/// This method doesn't check the actual type of <paramref name="obj"/>, so it is responsability of the caller
/// to ensure it actually represents a boxed <typeparamref name="T"/> value and not some other instance.
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Box<T> DangerousGetFrom(object obj)
{
return Unsafe.As<Box<T>>(obj);
}

/// <summary>
/// Tries to get a <see cref="Box{T}"/> reference from an input <see cref="object"/> representing a boxed <typeparamref name="T"/> value.
/// </summary>
/// <param name="obj">The input <see cref="object"/> instance to check.</param>
/// <param name="box">The resulting <see cref="Box{T}"/> reference, if <paramref name="obj"/> was a boxed <typeparamref name="T"/> value.</param>
/// <returns><see langword="true"/> if a <see cref="Box{T}"/> instance was retrieved correctly, <see langword="false"/> otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1115", Justification = "Comment for [NotNullWhen] attribute")]
public static bool TryGetFrom(
object obj,
#if NETSTANDARD2_1
/* On .NET Standard 2.1, we can add the [NotNullWhen] attribute
* to let the code analysis engine know that whenever this method
* returns true, box will always be assigned to a non-null value.
* This will eliminate the null warnings when in a branch that
* is only taken when this method returns true. */
[NotNullWhen(true)]
#endif
out Box<T>? box)
{
if (obj.GetType() == typeof(T))
{
box = Unsafe.As<Box<T>>(obj);

return true;
}

box = null;

return false;
}

/// <summary>
/// Implicitly gets the <typeparamref name="T"/> value from a given <see cref="Box{T}"/> instance.
/// </summary>
/// <param name="box">The input <see cref="Box{T}"/> instance.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator T(Box<T> box)
{
return Unsafe.Unbox<T>(box);
}

/// <summary>
/// Implicitly creates a new <see cref="Box{T}"/> instance from a given <typeparamref name="T"/> value.
/// </summary>
/// <param name="value">The input <typeparamref name="T"/> value to wrap.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Box<T>(T value)
{
/* The Box<T> type is never actually instantiated.
* Here we are just boxing the input T value, and then reinterpreting
* that object reference as a Box<T> reference. As such, the Box<T>
* type is really only used as an interface to access the contents
* of a boxed value type. This also makes it so that additional methods
* like ToString() or GetHashCode() will automatically be referenced from
* the method table of the boxed object, meaning that they don't need to
* manually be implemented in the Box<T> type. For instance, boxing a float
* and calling ToString() on it directly, on its boxed object or on a Box<T>
* reference retrieved from it will produce the same result in all cases. */
return Unsafe.As<Box<T>>(value);
}

/// <inheritdoc/>
public override string ToString()
{
/* Here we're overriding the base object virtual methods to ensure
* calls to those methods have a correct results on all runtimes.
* For instance, not doing so is causing issue on .NET Core 2.1 Release
* due to how the runtime handles the Box<T> reference to an actual
* boxed T value (not a concrete Box<T> instance as it would expect).
* To fix that, the overrides will simply call the expected methods
* directly on the boxed T values. These methods will be directly
* invoked by the JIT compiler when using a Box<T> reference. When
* an object reference is used instead, the call would be forwarded
* to those same methods anyway, since the method table for an object
* representing a T instance is the one of type T anyway. */
return this.GetReference().ToString();
}

/// <inheritdoc/>
public override bool Equals(object obj)
{
return Equals(this, obj);
}

/// <inheritdoc/>
public override int GetHashCode()
{
return this.GetReference().GetHashCode();
}

/// <summary>
/// Throws an <see cref="InvalidCastException"/> when a cast from an invalid <see cref="object"/> is attempted.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowInvalidCastExceptionForGetFrom()
{
throw new InvalidCastException($"Can't cast the input object to the type Box<{typeof(T)}>");
}
}

/// <summary>
/// Helpers for working with the <see cref="Box{T}"/> type.
/// </summary>
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402", Justification = "Extension class to replace instance methods for Box<T>")]
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204", Justification = "Extensions being declared after the type they apply to")]
public static class BoxExtensions
{
/// <summary>
/// Gets a <typeparamref name="T"/> reference from a <see cref="Box{T}"/> instance.
/// </summary>
/// <typeparam name="T">The type of reference to retrieve.</typeparam>
/// <param name="box">The input <see cref="Box{T}"/> instance.</param>
/// <returns>A <typeparamref name="T"/> reference to the boxed value within <paramref name="box"/>.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T GetReference<T>(this Box<T> box)
where T : struct
{
/* The reason why this method is an extension and is not part of
* the Box<T> type itself is that Box<T> is really just a mask
* used over object references, but it is never actually instantiated.
* Because of this, the method table of the objects in the heap will
* be the one of type T created by the runtime, and not the one of
* the Box<T> type. To avoid potential issues when invoking this method
* on different runtimes, which might handle that scenario differently,
* we use an extension method, which is just syntactic sugar for a static
* method belonging to another class. This isn't technically necessary,
* but it's just an extra precaution since the syntax for users remains
* exactly the same anyway. Here we just call the Unsafe.Unbox<T>(object)
* API, which is hidden away for users of the type for simplicity.
* Note that this API will always actually involve a conditional
* branch, which is introduced by the JIT compiler to validate the
* object instance being unboxed. But since the alternative of
* manually tracking the offset to the boxed data would be both
* more error prone, and it would still introduce some overhead,
* this doesn't really matter in this case anyway. */
return ref Unsafe.Unbox<T>(box);
}
}
}
Loading