├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── dependabot.yml └── workflows │ ├── merge-dependabot.yml │ └── on-push-do-docs.yml ├── .gitignore ├── apiCount.include.md ├── api_guard.include.md ├── api_list.include.md ├── code_of_conduct.md ├── contributing.md ├── license.txt ├── notes.txt ├── readme.md └── src ├── .editorconfig ├── .gitattributes ├── .nuget └── _._ ├── ApiBuilderTests ├── ApiBuilderTests.csproj ├── BuildApiTest.cs ├── GlobalUsings.cs ├── Identifier.cs └── RoslynExtensions.cs ├── Consume ├── Consume.cs ├── Consume.csproj ├── Debug.cs └── UnscopedRefUsage.cs ├── ConsumeBclMemory └── ConsumeBclMemory.csproj ├── ConsumeClassicReferences └── ConsumeClassicReferences.csproj ├── ConsumeConsumeBclMemory ├── Consume.cs └── ConsumeConsumeBclMemory.csproj ├── ConsumeCs13 └── ConsumeCs13.csproj ├── ConsumeCsDefault └── ConsumeCsDefault.csproj ├── ConsumeCsLatest └── ConsumeCsLatest.csproj ├── ConsumeCsLatestMajor └── ConsumeCsLatestMajor.csproj ├── ConsumeIndirect └── ConsumeIndirect.csproj ├── ConsumeNoOptional └── ConsumeNoOptional.csproj ├── ConsumeNoRefs └── ConsumeNoRefs.csproj ├── ConsumeOnlyCompression └── ConsumeOnlyCompression.csproj ├── ConsumeOnlyMemory └── ConsumeOnlyMemory.csproj ├── ConsumeOnlyTasks └── ConsumeOnlyTasks.csproj ├── ConsumeOnlyValueTuple └── ConsumeOnlyValueTuple.csproj ├── ConsumeUwp └── ConsumeUwp.csproj ├── Directory.Build.props ├── Directory.Packages.props ├── NoExtrasTests ├── GlobalUsings.cs ├── NoExtrasTests.csproj └── Tests.cs ├── NoRefsTests └── NoRefsTests.csproj ├── Polyfill.sln ├── Polyfill.sln.DotSettings ├── Polyfill.slnf ├── Polyfill ├── CallerArgumentExpressionAttribute.cs ├── CollectionBuilderAttribute.cs ├── CompilerFeatureRequiredAttribute.cs ├── ConstantExpectedAttribute.cs ├── ConvertPolyfill.cs ├── DateTimeOffsetPolyfill.cs ├── DateTimePolyfill.cs ├── DebuggerDisableUserUnhandledExceptionsAttribute.cs ├── DelegatePolyfill.cs ├── DisableRuntimeMarshallingAttribute.cs ├── EnumPolyfill.cs ├── ExperimentalAttribute.cs ├── FeatureGuardAttribute.cs ├── FeatureSwitchDefinitionAttribute.cs ├── FilePolyfill.cs ├── Guard │ ├── Guard.cs │ ├── Guard_NotEmpty.cs │ ├── Guard_NotNull.cs │ ├── Guard_NotNullOrEmpty.cs │ ├── Guard_NotNullOrWhiteSpace.cs │ └── Guard_NotWhiteSpace.cs ├── GuidPolyfill.cs ├── IndexRange │ ├── Index.cs │ └── Range.cs ├── IsExternalInit.cs ├── KeyValuePair.cs ├── Lock.cs ├── MathPolyfill.cs ├── ModuleInitializerAttribute.cs ├── Nullability │ ├── NullabilityInfo.cs │ ├── NullabilityInfoContext.cs │ └── NullabilityInfoExtensions.cs ├── Nullable │ ├── AllowNullAttribute.cs │ ├── DisallowNullAttribute.cs │ ├── DoesNotReturnAttribute.cs │ ├── DoesNotReturnIfAttribute.cs │ ├── MaybeNullAttribute.cs │ ├── MaybeNullWhenAttribute.cs │ ├── MemberNotNullAttribute.cs │ ├── MemberNotNullWhenAttribute.cs │ ├── NotNullAttribute.cs │ ├── NotNullIfNotNullAttribute.cs │ └── NotNullWhenAttribute.cs ├── Numbers │ ├── BytePolyfill.cs │ ├── DoublePolyfill.cs │ ├── IntPolyfill.cs │ ├── LongPolyfill.cs │ ├── SBytePolyfill.cs │ ├── ShortPolyfill.cs │ ├── UIntPolyfill.cs │ ├── ULongPolyfill.cs │ └── UShortPolyfill.cs ├── OperatingSystemPolyfill.cs ├── OverloadResolutionPriorityAttribute.cs ├── ParamCollectionAttribute.cs ├── PathPolyfill.cs ├── PlatformCompatibility │ ├── OSPlatformAttribute.cs │ ├── ObsoletedOSPlatformAttribute.cs │ ├── SupportedOSPlatformAttribute.cs │ ├── SupportedOSPlatformGuardAttribute.cs │ ├── TargetPlatformAttribute.cs │ ├── UnsupportedOSPlatformAttribute.cs │ └── UnsupportedOSPlatformGuardAttribute.cs ├── Polyfill.cs ├── Polyfill.csproj ├── Polyfill.nuspec ├── Polyfill.targets ├── Polyfill_CancellationToken.cs ├── Polyfill_CancellationTokenSource.cs ├── Polyfill_Compression.cs ├── Polyfill_ConcurrentBag.cs ├── Polyfill_ConcurrentDictionary.cs ├── Polyfill_ConcurrentQueue.cs ├── Polyfill_DateOnly.cs ├── Polyfill_DateTime.cs ├── Polyfill_DateTimeOffset.cs ├── Polyfill_DefaultInterpolatedStringHandler.cs ├── Polyfill_Delegate.cs ├── Polyfill_Dictionary.cs ├── Polyfill_DictionaryEntry.cs ├── Polyfill_Encoding.cs ├── Polyfill_Encoding_GetByteCount.cs ├── Polyfill_Encoding_GetCharCount.cs ├── Polyfill_Encoding_GetChars.cs ├── Polyfill_Encoding_TryGet.cs ├── Polyfill_HashSet.cs ├── Polyfill_HttpClient.cs ├── Polyfill_HttpContent.cs ├── Polyfill_IEnumerable_AggregateBy.cs ├── Polyfill_IEnumerable_Append.cs ├── Polyfill_IEnumerable_Chunk.cs ├── Polyfill_IEnumerable_CountBy.cs ├── Polyfill_IEnumerable_DistinctBy.cs ├── Polyfill_IEnumerable_ElementAt.cs ├── Polyfill_IEnumerable_Except.cs ├── Polyfill_IEnumerable_FirstOrDefault.cs ├── Polyfill_IEnumerable_Index.cs ├── Polyfill_IEnumerable_LastOrDefault.cs ├── Polyfill_IEnumerable_Max.cs ├── Polyfill_IEnumerable_MaxBy.cs ├── Polyfill_IEnumerable_Min.cs ├── Polyfill_IEnumerable_MinBy.cs ├── Polyfill_IEnumerable_SingleOrDefault.cs ├── Polyfill_IEnumerable_SkipLast.cs ├── Polyfill_IEnumerable_Take.cs ├── Polyfill_IEnumerable_TakeLast.cs ├── Polyfill_IEnumerable_ThrowHelper.cs ├── Polyfill_IEnumerable_ToHashSet.cs ├── Polyfill_IEnumerable_TryGetNonEnumeratedCount.cs ├── Polyfill_IEnumerable_Zip.cs ├── Polyfill_IReadOnlyDictionary.cs ├── Polyfill_KeyValuePair.cs ├── Polyfill_List.cs ├── Polyfill_Memory.cs ├── Polyfill_Memory_CommonPrefixLength.cs ├── Polyfill_Memory_Contains.cs ├── Polyfill_Memory_CountAny.cs ├── Polyfill_Memory_EndsWith.cs ├── Polyfill_Memory_IndexOf.cs ├── Polyfill_Memory_IndexOfAny.cs ├── Polyfill_Memory_SpanSplit.cs ├── Polyfill_Memory_SpanSplitEnumerator.cs ├── Polyfill_Memory_SpanSplitEnumeratorMode.cs ├── Polyfill_Memory_StartsWith.cs ├── Polyfill_MethodInfo.cs ├── Polyfill_MicroNanosecond.cs ├── Polyfill_MicroNanosecondAdd.cs ├── Polyfill_OrderedDictionary.cs ├── Polyfill_Process.cs ├── Polyfill_Queue.cs ├── Polyfill_Random.cs ├── Polyfill_Set.cs ├── Polyfill_SortedList.cs ├── Polyfill_Stack.cs ├── Polyfill_Stream.cs ├── Polyfill_Stream_DisposeAsync.cs ├── Polyfill_String.cs ├── Polyfill_StringBuilder.cs ├── Polyfill_StringBuilder_Append.cs ├── Polyfill_StringBuilder_AppendJoin.cs ├── Polyfill_StringBuilder_CopyTo.cs ├── Polyfill_StringBuilder_GetChunks.cs ├── Polyfill_StringBuilder_Insert.cs ├── Polyfill_StringBuilder_Replace.cs ├── Polyfill_StringNormalization.cs ├── Polyfill_Task.cs ├── Polyfill_TaskCompletionSource.cs ├── Polyfill_TextReader.cs ├── Polyfill_TextWriter.cs ├── Polyfill_TimeOnly.cs ├── Polyfill_TryFormatToByteSpan.cs ├── Polyfill_TryFormatToCharSpan.cs ├── Polyfill_Type.cs ├── Polyfill_XDocument.cs ├── RandomPolyfill.cs ├── Regex │ ├── Polyfill_Regex.cs │ ├── RegexCache.cs │ ├── RegexPolyfill.cs │ ├── ValueMatch.cs │ └── ValueMatchEnumerator.cs ├── RequiredMemberAttribute.cs ├── RequiresPreviewFeaturesAttribute.cs ├── ResolveHttpGlobalProblem.cs ├── SHA256Polyfill.cs ├── SHA512Polyfill.cs ├── SetsRequiredMembersAttribute.cs ├── SkipLocalsInitAttribute.cs ├── SpanLineEnumerator.cs ├── StackTraceHiddenAttribute.cs ├── StringInterpolation │ ├── AppendInterpolatedStringHandler.cs │ ├── DefaultInterpolatedStringHandler.cs │ ├── InterpolatedStringHandlerArgumentAttribute.cs │ ├── InterpolatedStringHandlerAttribute.cs │ ├── Polyfill_StringBuilder_Append.cs │ └── Polyfill_StringBuilder_AppendLine.cs ├── StringPolyfill.cs ├── StringSyntaxAttribute.cs ├── SuppressGCTransitionAttribute.cs ├── TaskCompletionSource.cs ├── Trimming │ ├── DynamicDependencyAttribute.cs │ ├── DynamicallyAccessedMemberTypes.cs │ ├── DynamicallyAccessedMembersAttribute.cs │ ├── RequiresDynamicCodeAttribute.cs │ ├── RequiresUnreferencedCodeAttribute.cs │ └── UnconditionalSuppressMessageAttribute.cs ├── UnmanagedCallersOnlyAttribute.cs ├── UnreachableException.cs ├── UnscopedRefAttribute.cs └── exclude.editorconfig ├── PolyfillLib └── PolyfillLib.csproj ├── PolyfillUwp.sln ├── PolyfillUwp.sln.DotSettings ├── PublicTests └── PublicTests.csproj ├── Shared.sln.DotSettings ├── TargetFrameworkUsage ├── FakePolyfillsNamespace.cs └── TargetFrameworkUsage.csproj ├── TestIncludes.targets ├── Tests ├── CallerArgumentExpressionUsage.cs ├── CollectionBuilderAttributeTests.cs ├── ConstantExpectedTests.cs ├── ConvertPolyfillTests.cs ├── FilePolyfillTests.cs ├── GlobalUsings.cs ├── GuardTests.cs ├── IndexRangeSample.cs ├── InitSample.cs ├── LockTests.cs ├── Memory_CommonPrefixLength.cs ├── ModuleInitSample.cs ├── NamedTupleSample.cs ├── NullabilitySamples.cs ├── Numbers │ ├── BytePolyfillTests.cs │ ├── DoublePolyfillTests.cs │ ├── IntPolyfillTests.cs │ ├── LongPolyfillTests.cs │ ├── SBytePolyfillTests.cs │ ├── ShortPolyfillTests.cs │ ├── UIntPolyfillTests.cs │ ├── ULongPolyfill.cs │ └── UShortPolyfillTests.cs ├── OverloadResolutionPriorityAttributeTests.cs ├── PathTests.cs ├── PolyfillTests.cs ├── PolyfillTests_CancellationToken.cs ├── PolyfillTests_CancellationTokenSource.cs ├── PolyfillTests_Compression.cs ├── PolyfillTests_ConcurrentBag.cs ├── PolyfillTests_ConcurrentDictionary.cs ├── PolyfillTests_ConcurrentQueue.cs ├── PolyfillTests_Delegate.cs ├── PolyfillTests_Dictionary.cs ├── PolyfillTests_Encoding.cs ├── PolyfillTests_Enum.cs ├── PolyfillTests_Guid.cs ├── PolyfillTests_HashSet.cs ├── PolyfillTests_HttpClient.cs ├── PolyfillTests_IEnumerable.cs ├── PolyfillTests_IEnumerable_MinMax.cs ├── PolyfillTests_IReadOnlyDictionary.cs ├── PolyfillTests_List.cs ├── PolyfillTests_Memory.cs ├── PolyfillTests_Memory_CountAny.cs ├── PolyfillTests_Memory_IndexOf.cs ├── PolyfillTests_Memory_IndexOfAny.cs ├── PolyfillTests_Memory_Split.cs ├── PolyfillTests_MicroNanosecond.cs ├── PolyfillTests_Normalization.cs ├── PolyfillTests_OperatingSystem.cs ├── PolyfillTests_OrderedDictionary.cs ├── PolyfillTests_Process.cs ├── PolyfillTests_Random.cs ├── PolyfillTests_Regex.cs ├── PolyfillTests_SortedList.cs ├── PolyfillTests_Stack.cs ├── PolyfillTests_Stream.cs ├── PolyfillTests_StreamReader.cs ├── PolyfillTests_String.cs ├── PolyfillTests_StringBuilder.cs ├── PolyfillTests_Task.cs ├── PolyfillTests_TaskCompletionSource.cs ├── PolyfillTests_TextWriter.cs ├── PolyfillTests_TryFormatToByteSpan.cs ├── PolyfillTests_TryFormatToCharSpan.cs ├── PolyfillTests_Type.cs ├── PolyfillTests_XDocument.cs ├── RandomPolyfillTests.cs ├── RangeIndexUsage.cs ├── SanityChecks.cs ├── SetsRequiredMembersUsage.cs ├── Sha256PolyfillTests.cs ├── Sha512PolyfillTests.cs ├── SolutionDirectoryFinder.cs ├── StringInterpolationTests.cs ├── StringPolyfillTests.cs ├── Tests.csproj └── UnreachableExceptionTests.cs ├── UnsafeTests ├── SkipLocalsInitExample.cs └── UnsafeTests.csproj ├── appveyor.yml ├── editorconfig.txt ├── global.json ├── icon.png ├── key.snk ├── mdsnippets.json └── nuget.config /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: SimonCropp -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: How to raise feature requests 4 | --- 5 | 6 | 7 | Note: New issues raised, where it is clear the submitter has not read the issue template, are likely to be closed with "please read the issue template". Please don't take offense at this. It is simply a time management decision. If someone raises an issue, and can't be bothered to spend the time to read the issue template, then the project maintainers should not be expected to spend the time to read the submitted issue. Often too much time is spent going back and forth in issue comments asking for information that is outlined in the issue template. 8 | 9 | If you are certain the feature will be accepted, it is better to raise a [Pull Request (PR)](https://help.github.com/articles/about-pull-requests/). 10 | 11 | If you are uncertain if the feature will be accepted, outline the proposal below to confirm it is viable, prior to raising a PR that implements the feature. 12 | 13 | Note that even if the feature is a good idea and viable, it may not be accepted since the ongoing effort in maintaining the feature may outweigh the benefit it delivers. 14 | 15 | 16 | #### Is the feature request related to a problem 17 | 18 | A clear and concise description of what the problem is. 19 | 20 | 21 | #### Describe the solution 22 | 23 | A clear and concise proposal of how you intend to implement the feature. 24 | 25 | 26 | #### Describe alternatives considered 27 | 28 | A clear and concise description of any alternative solutions or features you've considered. 29 | 30 | 31 | #### Additional context 32 | 33 | Add any other context about the feature request here. 34 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: nuget 4 | directory: "/src" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.github/workflows/merge-dependabot.yml: -------------------------------------------------------------------------------- 1 | name: merge-dependabot 2 | on: 3 | pull_request: 4 | jobs: 5 | automerge: 6 | runs-on: ubuntu-latest 7 | if: github.actor == 'dependabot[bot]' 8 | steps: 9 | - name: Dependabot Auto Merge 10 | uses: ahmadnassri/action-dependabot-auto-merge@v2.6.6 11 | with: 12 | target: minor 13 | github-token: ${{ secrets.dependabot }} 14 | command: squash and merge -------------------------------------------------------------------------------- /.github/workflows/on-push-do-docs.yml: -------------------------------------------------------------------------------- 1 | name: on-push-do-docs 2 | on: 3 | push: 4 | jobs: 5 | docs: 6 | runs-on: windows-latest 7 | steps: 8 | - uses: actions/checkout@v4 9 | - name: Run MarkdownSnippets 10 | run: | 11 | dotnet tool install --global MarkdownSnippets.Tool 12 | mdsnippets ${GITHUB_WORKSPACE} 13 | shell: bash 14 | - name: Push changes 15 | run: | 16 | git config --local user.email "action@github.com" 17 | git config --local user.name "GitHub Action" 18 | git commit -m "Docs changes" -a || echo "nothing to commit" 19 | remote="https://${GITHUB_ACTOR}:${{secrets.GITHUB_TOKEN}}@github.com/${GITHUB_REPOSITORY}.git" 20 | branch="${GITHUB_REF:11}" 21 | git push "${remote}" ${branch} || echo "nothing to push" 22 | shell: bash -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | bin/ 4 | obj/ 5 | .vs/ 6 | *.DotSettings.user 7 | .idea/ 8 | *.received.* 9 | nugets/ 10 | src/msbuild.binlog 11 | -------------------------------------------------------------------------------- /apiCount.include.md: -------------------------------------------------------------------------------- 1 | **API count: 607** -------------------------------------------------------------------------------- /api_guard.include.md: -------------------------------------------------------------------------------- 1 | #### Guard 2 | 3 | * `void DirectoryExists(String)` 4 | * `void FileExists(String)` 5 | * `void NotEmpty(String)` 6 | * `void NotEmpty(ReadOnlySpan)` 7 | * `void NotEmpty(Span)` 8 | * `void NotEmpty(Nullable>)` 9 | * `void NotEmpty(Memory)` 10 | * `void NotEmpty(Nullable>)` 11 | * `void NotEmpty(ReadOnlyMemory)` 12 | * `void NotEmpty(T) where T : Collections.IEnumerable` 13 | * `T NotNull(T)` 14 | * `String NotNull(String)` 15 | * `String NotNullOrEmpty(String)` 16 | * `T NotNullOrEmpty(T) where T : Collections.IEnumerable` 17 | * `Memory NotNullOrEmpty(Nullable>)` 18 | * `ReadOnlyMemory NotNullOrEmpty(Nullable>)` 19 | * `String NotNullOrWhiteSpace(String)` 20 | * `Memory NotNullOrWhiteSpace(Nullable>)` 21 | * `ReadOnlyMemory NotNullOrWhiteSpace(Nullable>)` 22 | * `void NotWhiteSpace(String)` 23 | * `void NotWhiteSpace(ReadOnlySpan)` 24 | * `void NotWhiteSpace(Nullable>)` 25 | * `void NotWhiteSpace(Nullable>)` 26 | * `void NotWhiteSpace(Span)` 27 | 28 | 29 | -------------------------------------------------------------------------------- /code_of_conduct.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the code of conduct defined by the Contributor Covenant 4 | to clarify expected behavior in our community. 5 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/about/code-of-conduct). 6 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Simon Cropp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | https://github.com/dotnet/core/blob/main/release-notes/6.0/api-diff/.Net/6.0.0_System.Linq.md 2 | https://github.com/dotnet/core/blob/main/release-notes/9.0/preview/preview2/api-diff/Microsoft.NETCore.App/9.0-preview2_System.IO.md 3 | https://github.com/dotnet/core/blob/main/release-notes/8.0/8.0.0/api-diff/Microsoft.NETCore.App/8.0.0_System.Collections.Generic.md 4 | https://github.com/dotnet/core/blob/main/release-notes/8.0/8.0.0/api-diff/Microsoft.NETCore.App/8.0.0_System.md 5 | https://github.com/dotnet/core/blob/main/release-notes/7.0/7.0.0/api-diff/Microsoft.NETCore.App/7.0.0_System.Collections.Immutable.md 6 | 7 | 8 | public static IEnumerable IntersectBy(this IEnumerable first, IEnumerable second, Func keySelector); 9 | public static IEnumerable IntersectBy(this IEnumerable first, IEnumerable second, Func keySelector, IEqualityComparer comparer); 10 | public static IEnumerable UnionBy(this IEnumerable first, IEnumerable second, Func keySelector); 11 | public static IEnumerable UnionBy(this IEnumerable first, IEnumerable second, Func keySelector, IEqualityComparer comparer); 12 | -------------------------------------------------------------------------------- /src/.gitattributes: -------------------------------------------------------------------------------- 1 | * text 2 | *.snk binary 3 | *.png binary 4 | 5 | *.verified.txt text eol=lf working-tree-encoding=UTF-8 6 | *.verified.xml text eol=lf working-tree-encoding=UTF-8 7 | *.verified.json text eol=lf working-tree-encoding=UTF-8 8 | 9 | .editorconfig text eol=lf working-tree-encoding=UTF-8 10 | Shared.sln.DotSettings text eol=lf working-tree-encoding=UTF-8 -------------------------------------------------------------------------------- /src/.nuget/_._: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonCropp/Polyfill/c7653d6b0f4592e732bc62c201fc7354d7e6b0ac/src/.nuget/_._ -------------------------------------------------------------------------------- /src/ApiBuilderTests/ApiBuilderTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net10.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | SolutionDirectoryFinder.cs 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/ApiBuilderTests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using NUnit.Framework; 2 | global using System; 3 | global using System.Diagnostics.CodeAnalysis; 4 | global using Microsoft.CodeAnalysis; 5 | global using Microsoft.CodeAnalysis.CSharp; 6 | global using Microsoft.CodeAnalysis.CSharp.Syntax; -------------------------------------------------------------------------------- /src/ApiBuilderTests/Identifier.cs: -------------------------------------------------------------------------------- 1 | public class Identifier 2 | { 3 | public required string Moniker { get; init; } 4 | public required List Directives { get; init; } 5 | } -------------------------------------------------------------------------------- /src/ApiBuilderTests/RoslynExtensions.cs: -------------------------------------------------------------------------------- 1 | public static class RoslynExtensions 2 | { 3 | public static bool IsPublic(this MemberDeclarationSyntax member) => 4 | member.Modifiers.Any(_ => _.ValueText == "public"); 5 | 6 | public static bool IsNested(this TypeDeclarationSyntax type) => 7 | type.Parent is TypeDeclarationSyntax or ClassDeclarationSyntax; 8 | 9 | public static bool IsStatic(this MethodDeclarationSyntax method) => 10 | method.Modifiers.Any(_ => _.IsKind(SyntaxKind.StaticKeyword)); 11 | 12 | public static IEnumerable PublicMethods(this TypeDeclarationSyntax typeDeclaration) => 13 | typeDeclaration 14 | .DescendantNodes() 15 | .OfType() 16 | .Where(_ => _.Parent == typeDeclaration && 17 | _.IsPublic() && 18 | !_.IsConstructor()); 19 | 20 | public static bool IsConstructor(this MethodDeclarationSyntax method) 21 | { 22 | if (method.Parent is TypeDeclarationSyntax typeDeclaration) 23 | { 24 | return method.Identifier.Text == typeDeclaration.Identifier.Text; 25 | } 26 | 27 | return false; 28 | } 29 | 30 | public static bool IsCaller(this ParameterSyntax parameter) => 31 | parameter.Attributes() 32 | .Any(_ => _.Name.ToString().StartsWith("Caller")); 33 | 34 | public static IEnumerable Attributes(this MethodDeclarationSyntax method) => 35 | method.AttributeLists 36 | .SelectMany(_ => _.Attributes); 37 | 38 | public static IEnumerable Attributes(this ParameterSyntax method) => 39 | method.AttributeLists 40 | .SelectMany(_ => _.Attributes); 41 | 42 | public static string Value(this AttributeArgumentSyntax argument) => 43 | argument.Expression.ToString(); 44 | } -------------------------------------------------------------------------------- /src/Consume/Consume.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Consume/Debug.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | // Test to make sure there are no clashes in the Polyfill code with classes that might be defined in user code. 4 | // 5 | // Some codebases, for better or for worse, define classes with names that match common classes in the base 6 | // .NET libraries, like "Debug". This works find in those codebases because they are usually contained in the 7 | // same namespace, or are guarded in some other way. But if a Polyfill attribute is imported and uses code like: 8 | // Debug.Assert(genericParameter.IsGenericParameter); 9 | // instead of a fully qualified name like: 10 | // System.Debug.Assert(genericParameter.IsGenericParameter); 11 | // then users of Polyfill will get errors like the following, which they can't easily fix: 12 | // 'Debug' does not contain a definition for 'Assert' 13 | // 14 | // So, this file defines a custom Debug class to make sure that Polyfill code doesn't clash with user code. 15 | class Debug 16 | { 17 | public static void Log(string content) => Console.WriteLine(content); 18 | 19 | public static void Log(ConsoleColor color, string content) 20 | { 21 | Console.ForegroundColor = color; 22 | Console.WriteLine(content); 23 | Console.ResetColor(); 24 | } 25 | 26 | public static void LogWarning(string content) => Log(ConsoleColor.Yellow, content); 27 | public static void LogError(string content) => Log(ConsoleColor.Red, content); 28 | } 29 | -------------------------------------------------------------------------------- /src/Consume/UnscopedRefUsage.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | #pragma warning disable CS0169 // Field is never used 3 | 4 | // ReSharper disable once ReplaceWithFieldKeyword 5 | #region UnscopedRefUsage 6 | struct UnscopedRefUsage 7 | { 8 | int field1; 9 | 10 | [UnscopedRef] ref int Prop1 => ref field1; 11 | } 12 | #endregion -------------------------------------------------------------------------------- /src/ConsumeBclMemory/ConsumeBclMemory.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 5 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/ConsumeClassicReferences/ConsumeClassicReferences.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 6 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/ConsumeConsumeBclMemory/Consume.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | static class Consume 4 | { 5 | static Consume() 6 | { 7 | var strings = new List(); 8 | var last = strings[^1]; 9 | } 10 | } -------------------------------------------------------------------------------- /src/ConsumeConsumeBclMemory/ConsumeConsumeBclMemory.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 5 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/ConsumeCs13/ConsumeCs13.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | 13.0 6 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 7 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/ConsumeCsDefault/ConsumeCsDefault.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | default 6 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 7 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/ConsumeCsLatest/ConsumeCsLatest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | latest 6 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 7 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/ConsumeCsLatestMajor/ConsumeCsLatestMajor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | latestMajor 6 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 7 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/ConsumeIndirect/ConsumeIndirect.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 6 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/ConsumeNoOptional/ConsumeNoOptional.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | false 7 | false 8 | false 9 | $(DefineConstants);NoStringInterpolation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/ConsumeNoRefs/ConsumeNoRefs.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows 6 | $(TargetFrameworks);netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/ConsumeOnlyCompression/ConsumeOnlyCompression.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/ConsumeOnlyMemory/ConsumeOnlyMemory.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/ConsumeOnlyTasks/ConsumeOnlyTasks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/ConsumeOnlyValueTuple/ConsumeOnlyValueTuple.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | net461;net462;net47;net471;net472;net48;net481;net6.0-windows;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/ConsumeUwp/ConsumeUwp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | uap10.0.16299 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CS1591;NETSDK1138;NU1901;NU1902;NU1903;CA1822;CA1847;CA1861;NU1510;NU1608;NU1109 5 | 8.0.0-beta.3 6 | 1.0.0 7 | Polyfill 8 | true 9 | false 10 | false 11 | preview 12 | false 13 | true 14 | true 15 | true 16 | true 17 | true 18 | true 19 | true 20 | true 22 | 23 | -------------------------------------------------------------------------------- /src/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/NoExtrasTests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Global using directives 2 | 3 | global using NUnit.Framework; -------------------------------------------------------------------------------- /src/NoExtrasTests/NoExtrasTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | net10.0 5 | false 6 | false 7 | false 8 | NoExtras 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/NoExtrasTests/Tests.cs: -------------------------------------------------------------------------------- 1 | [TestFixture] 2 | public class Tests 3 | { 4 | [Test] 5 | public void NoGuard() => 6 | Assert.IsNull(GetType().Assembly.GetType("Polyfills.Guard")); 7 | 8 | [Test] 9 | public void NoNullExtensions() 10 | { 11 | var method = typeof(Polyfill) 12 | .GetMethod("GetNullabilityInfo", BindingFlags.Static | BindingFlags.Public, null, [typeof(MemberInfo)], null); 13 | Assert.IsNull(method); 14 | } 15 | } -------------------------------------------------------------------------------- /src/NoRefsTests/NoRefsTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | net462;net472;net48;net6.0-windows 5 | $(TargetFrameworks);netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Polyfill.slnf: -------------------------------------------------------------------------------- 1 | { 2 | "solution": { 3 | "path": "Polyfill.sln", 4 | "projects": [ 5 | "ApiBuilderTests\\ApiBuilderTests.csproj", 6 | "Consume\\Consume.csproj", 7 | "Polyfill\\Polyfill.csproj", 8 | "TargetFrameworkUsage\\TargetFrameworkUsage.csproj", 9 | "Tests\\Tests.csproj" 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /src/Polyfill/CallerArgumentExpressionAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Indicates that a parameter captures the expression passed for another parameter as a string. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage(AttributeTargets.Parameter)] 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callerargumentexpressionattribute?view=net-10.0 18 | #if PolyPublic 19 | public 20 | #endif 21 | sealed class CallerArgumentExpressionAttribute : 22 | Attribute 23 | { 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// 27 | public CallerArgumentExpressionAttribute(string parameterName) => 28 | ParameterName = parameterName; 29 | 30 | /// 31 | /// Gets the name of the parameter whose expression should be captured as a string. 32 | /// 33 | public string ParameterName { get; } 34 | } 35 | 36 | #else 37 | using System.Runtime.CompilerServices; 38 | [assembly: TypeForwardedTo(typeof(CallerArgumentExpressionAttribute))] 39 | #endif -------------------------------------------------------------------------------- /src/Polyfill/CollectionBuilderAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if FeatureMemory 5 | #if !NET8_0_OR_GREATER 6 | 7 | namespace System.Runtime.CompilerServices; 8 | 9 | using Diagnostics; 10 | using Diagnostics.CodeAnalysis; 11 | 12 | [ExcludeFromCodeCoverage] 13 | [DebuggerNonUserCode] 14 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.collectionbuilderattribute?view=net-10.0 16 | #if PolyPublic 17 | public 18 | #endif 19 | sealed class CollectionBuilderAttribute : Attribute 20 | { 21 | /// Initialize the attribute to refer to the method on the type. 22 | public CollectionBuilderAttribute(Type builderType, string methodName) 23 | { 24 | BuilderType = builderType; 25 | MethodName = methodName; 26 | } 27 | 28 | /// Gets the type of the builder to use to construct the collection. 29 | public Type BuilderType { get; } 30 | 31 | /// Gets the name of the method on the builder to use to construct the collection. 32 | public string MethodName { get; } 33 | } 34 | #else 35 | using System.Runtime.CompilerServices; 36 | [assembly: TypeForwardedTo(typeof(CollectionBuilderAttribute))] 37 | #endif 38 | #endif -------------------------------------------------------------------------------- /src/Polyfill/CompilerFeatureRequiredAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Indicates that compiler support for a particular feature is required for the location where this attribute is applied. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: AttributeTargets.All, 18 | AllowMultiple = true, 19 | Inherited = false)] 20 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.compilerfeaturerequiredattribute?view=net-10.0 21 | #if PolyPublic 22 | public 23 | #endif 24 | sealed class CompilerFeatureRequiredAttribute : 25 | Attribute 26 | { 27 | /// 28 | /// Initialize a new instance of 29 | /// 30 | public CompilerFeatureRequiredAttribute(string featureName) => 31 | FeatureName = featureName; 32 | 33 | /// 34 | /// The name of the compiler feature. 35 | /// 36 | public string FeatureName { get; } 37 | 38 | /// 39 | /// If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand . 40 | /// 41 | public bool IsOptional { get; init; } 42 | 43 | /// 44 | /// The used for the ref structs C# feature. 45 | /// 46 | public const string RefStructs = nameof(RefStructs); 47 | 48 | /// 49 | /// The used for the required members C# feature. 50 | /// 51 | public const string RequiredMembers = nameof(RequiredMembers); 52 | } 53 | 54 | #else 55 | using System.Runtime.CompilerServices; 56 | [assembly: TypeForwardedTo(typeof(CompilerFeatureRequiredAttribute))] 57 | #endif -------------------------------------------------------------------------------- /src/Polyfill/ConstantExpectedAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | #nullable enable 7 | namespace System.Diagnostics.CodeAnalysis; 8 | 9 | using Diagnostics; 10 | 11 | /// 12 | /// Indicates that the specified method parameter expects a constant. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.constantexpectedattribute?view=net-10.0 18 | #if PolyPublic 19 | public 20 | #endif 21 | sealed class ConstantExpectedAttribute : Attribute 22 | { 23 | /// 24 | /// Indicates the minimum bound of the expected constant, inclusive. 25 | /// 26 | public object? Min { get; set; } 27 | /// 28 | /// Indicates the maximum bound of the expected constant, inclusive. 29 | /// 30 | public object? Max { get; set; } 31 | } 32 | #else 33 | using System.Runtime.CompilerServices; 34 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute))] 35 | #endif -------------------------------------------------------------------------------- /src/Polyfill/DebuggerDisableUserUnhandledExceptionsAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET9_0_OR_GREATER 5 | 6 | namespace System.Diagnostics; 7 | 8 | using Diagnostics.CodeAnalysis; 9 | 10 | /// 11 | /// If a .NET Debugger is attached that supports the API, the debugger won't break on user-unhandled exceptions when the exception is caught by a method with this attribute, unless is called. 12 | /// 13 | [ExcludeFromCodeCoverage] 14 | [DebuggerNonUserCode] 15 | [AttributeUsage(System.AttributeTargets.Method)] 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.debuggerdisableuserunhandledexceptionsattribute?view=net-10.0 17 | #if PolyPublic 18 | public 19 | #endif 20 | sealed class DebuggerDisableUserUnhandledExceptionsAttribute : 21 | Attribute; 22 | #else 23 | using System.Runtime.CompilerServices; 24 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.DebuggerDisableUserUnhandledExceptionsAttribute))] 25 | #endif -------------------------------------------------------------------------------- /src/Polyfill/DisableRuntimeMarshallingAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Disables the built-in runtime managed/unmanaged marshalling subsystem for 13 | /// P/Invokes, Delegate types, and unmanaged function pointer invocations. 14 | /// 15 | [ExcludeFromCodeCoverage] 16 | [DebuggerNonUserCode] 17 | [AttributeUsage(AttributeTargets.Assembly)] 18 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.disableruntimemarshallingattribute?view=net-10.0 19 | #if PolyPublic 20 | public 21 | #endif 22 | sealed class DisableRuntimeMarshallingAttribute : 23 | Attribute; 24 | #else 25 | using System.Runtime.CompilerServices; 26 | [assembly: TypeForwardedTo(typeof(DisableRuntimeMarshallingAttribute))] 27 | #endif -------------------------------------------------------------------------------- /src/Polyfill/FeatureGuardAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET9_0_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Diagnostics; 9 | 10 | /// 11 | /// Indicates that the specified public static boolean get-only property 12 | /// guards access to the specified feature. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)] 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.featureguardattribute 18 | #if PolyPublic 19 | public 20 | #endif 21 | sealed class FeatureGuardAttribute : Attribute 22 | { 23 | /// 24 | /// Initializes a new instance of the class 25 | /// with the specified feature type. 26 | /// 27 | public FeatureGuardAttribute(Type featureType) => 28 | FeatureType = featureType; 29 | 30 | /// 31 | /// The type that represents the feature guarded by the property. 32 | /// 33 | public Type FeatureType { get; } 34 | } 35 | #else 36 | using System.Runtime.CompilerServices; 37 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.FeatureGuardAttribute))] 38 | #endif -------------------------------------------------------------------------------- /src/Polyfill/FeatureSwitchDefinitionAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET9_0_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Diagnostics; 9 | 10 | /// 11 | /// [AttributeUsage(AttributeTargets.Property, Inherited = false)] 12 | /// 13 | [ExcludeFromCodeCoverage] 14 | [DebuggerNonUserCode] 15 | [AttributeUsage(AttributeTargets.Property, Inherited = false)] 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.featureswitchdefinitionattribute?view=net-10.0 17 | #if PolyPublic 18 | public 19 | #endif 20 | sealed class FeatureSwitchDefinitionAttribute : Attribute 21 | { 22 | /// 23 | /// Initializes a new instance of the class 24 | /// with the specified feature switch name. 25 | /// 26 | public FeatureSwitchDefinitionAttribute(string switchName) => SwitchName = switchName; 27 | 28 | /// 29 | /// The name of the feature switch that provides the value for the specified property. 30 | /// 31 | public string SwitchName { get; } 32 | } 33 | #else 34 | using System.Runtime.CompilerServices; 35 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.FeatureSwitchDefinitionAttribute))] 36 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Guard/Guard.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | namespace Polyfills; 4 | 5 | using System.Runtime.CompilerServices; 6 | 7 | #pragma warning disable 8 | 9 | using System; 10 | using System.IO; 11 | using System.Diagnostics; 12 | using System.Diagnostics.CodeAnalysis; 13 | 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [StackTraceHidden] 17 | #if PolyPublic 18 | public 19 | #endif 20 | static partial class Guard 21 | { 22 | public static void FileExists(string path, [CallerArgumentExpression("path")] string argumentName = "") 23 | { 24 | NotNullOrEmpty(path, argumentName); 25 | if (!File.Exists(path)) 26 | { 27 | throw new ArgumentException($"File not found. Path: {path}", argumentName); 28 | } 29 | } 30 | 31 | public static void DirectoryExists(string path, [CallerArgumentExpression("path")] string argumentName = "") 32 | { 33 | NotNullOrEmpty(path, argumentName); 34 | if (!Directory.Exists(path)) 35 | { 36 | throw new ArgumentException($"Directory not found. Path: {path}", argumentName); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/Polyfill/Guard/Guard_NotNull.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | namespace Polyfills; 5 | 6 | using System; 7 | using System.Runtime.CompilerServices; 8 | using System.Diagnostics.CodeAnalysis; 9 | 10 | #if PolyPublic 11 | public 12 | #endif 13 | static partial class Guard 14 | { 15 | public static T NotNull( 16 | [NotNull] T? argument, 17 | [CallerArgumentExpression("argument")] string? name = null) 18 | where T : class 19 | { 20 | if (argument is null) 21 | { 22 | throw new ArgumentNullException(name); 23 | } 24 | 25 | return argument; 26 | } 27 | 28 | public static string NotNull( 29 | [NotNull] string? argument, 30 | [CallerArgumentExpression("argument")] string? name = null) 31 | { 32 | if (argument is null) 33 | { 34 | throw new ArgumentNullException(name); 35 | } 36 | 37 | return argument; 38 | } 39 | } -------------------------------------------------------------------------------- /src/Polyfill/IsExternalInit.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Reserved to be used by the compiler for tracking metadata. This class should not be used by developers in source code. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.isexternalinit?view=net-10.0 17 | #if PolyPublic 18 | public 19 | #endif 20 | static class IsExternalInit; 21 | 22 | #else 23 | using System.Runtime.CompilerServices; 24 | [assembly: TypeForwardedTo(typeof(IsExternalInit))] 25 | #endif -------------------------------------------------------------------------------- /src/Polyfill/KeyValuePair.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if NETFRAMEWORK || NETSTANDARD2_0 5 | #nullable enable 6 | 7 | namespace System.Collections.Generic; 8 | 9 | using System.Diagnostics; 10 | using System.Diagnostics.CodeAnalysis; 11 | 12 | [ExcludeFromCodeCoverage] 13 | [DebuggerNonUserCode] 14 | // Provides the Create factory method for KeyValuePair. 15 | // https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.keyvaluepair?view=net-10.0 16 | #if PolyPublic 17 | public 18 | #endif 19 | static class KeyValuePair 20 | { 21 | /// 22 | /// Creates a new key/value pair instance using provided values. 23 | /// 24 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.keyvaluepair.create?view=net-10.0 25 | public static KeyValuePair Create(TKey key, TValue value) => 26 | new(key, value); 27 | } 28 | #else 29 | using System.Runtime.CompilerServices; 30 | [assembly: TypeForwardedTo(typeof(System.Collections.Generic.KeyValuePair))] 31 | #endif 32 | -------------------------------------------------------------------------------- /src/Polyfill/ModuleInitializerAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using System.Diagnostics; 9 | using System.Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Used to indicate to the compiler that a method should be called 13 | /// in its containing module's initializer. 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.moduleinitializerattribute?view=net-10.0 16 | [ExcludeFromCodeCoverage] 17 | [DebuggerNonUserCode] 18 | [AttributeUsage( 19 | validOn: AttributeTargets.Method, 20 | Inherited = false)] 21 | #if PolyPublic 22 | public 23 | #endif 24 | sealed class ModuleInitializerAttribute : 25 | Attribute; 26 | #else 27 | using System.Runtime.CompilerServices; 28 | [assembly: TypeForwardedTo(typeof(ModuleInitializerAttribute))] 29 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/AllowNullAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Targets = AttributeTargets; 9 | 10 | /// 11 | /// Specifies that is allowed as an input even if the 12 | /// corresponding type disallows it. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: Targets.Field | 18 | Targets.Parameter | 19 | Targets.Property)] 20 | #if PolyPublic 21 | public 22 | #endif 23 | sealed class AllowNullAttribute : 24 | Attribute; 25 | #else 26 | using System.Runtime.CompilerServices; 27 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.AllowNullAttribute))] 28 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/DisallowNullAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Targets = AttributeTargets; 9 | 10 | /// 11 | /// Specifies that is disallowed as an input even if the 12 | /// corresponding type allows it. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: Targets.Field | 18 | Targets.Parameter | 19 | Targets.Property)] 20 | #if PolyPublic 21 | public 22 | #endif 23 | sealed class DisallowNullAttribute : 24 | Attribute; 25 | #else 26 | using System.Runtime.CompilerServices; 27 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DisallowNullAttribute))] 28 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/DoesNotReturnAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | /// 9 | /// Specifies that a method that will never return under any circumstance. 10 | /// 11 | [ExcludeFromCodeCoverage] 12 | [DebuggerNonUserCode] 13 | [AttributeUsage( 14 | validOn: AttributeTargets.Method, 15 | Inherited = false)] 16 | #if PolyPublic 17 | public 18 | #endif 19 | sealed class DoesNotReturnAttribute : 20 | Attribute; 21 | #else 22 | using System.Runtime.CompilerServices; 23 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute))] 24 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/DoesNotReturnIfAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | /// 9 | /// Specifies that the method will not return if the associated 10 | /// parameter is passed the specified value. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | [DebuggerNonUserCode] 14 | [AttributeUsage(AttributeTargets.Parameter)] 15 | #if PolyPublic 16 | public 17 | #endif 18 | sealed class DoesNotReturnIfAttribute : 19 | Attribute 20 | { 21 | /// 22 | /// Gets the condition parameter value. 23 | /// Code after the method is considered unreachable by diagnostics if the argument 24 | /// to the associated parameter matches this value. 25 | /// 26 | public bool ParameterValue { get; } 27 | 28 | /// 29 | /// Initializes a new instance of the 30 | /// class with the specified parameter value. 31 | /// 32 | public DoesNotReturnIfAttribute(bool parameterValue) => 33 | ParameterValue = parameterValue; 34 | } 35 | #else 36 | using System.Runtime.CompilerServices; 37 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute))] 38 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/MaybeNullAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Targets = AttributeTargets; 9 | 10 | /// 11 | /// Specifies that an output may be even if the 12 | /// corresponding type disallows it. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: Targets.Field | 18 | Targets.Parameter | 19 | Targets.Property | 20 | Targets.ReturnValue)] 21 | #if PolyPublic 22 | public 23 | #endif 24 | sealed class MaybeNullAttribute : 25 | Attribute; 26 | #else 27 | using System.Runtime.CompilerServices; 28 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MaybeNullAttribute))] 29 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/MaybeNullWhenAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | /// 9 | /// Specifies that when a method returns , 10 | /// the parameter may be even if the corresponding type disallows it. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | [DebuggerNonUserCode] 14 | [AttributeUsage(AttributeTargets.Parameter)] 15 | #if PolyPublic 16 | public 17 | #endif 18 | sealed class MaybeNullWhenAttribute : 19 | Attribute 20 | { 21 | /// 22 | /// Gets the return value condition. 23 | /// If the method returns this value, the associated parameter may be . 24 | /// 25 | public bool ReturnValue { get; } 26 | 27 | /// 28 | /// Initializes the attribute with the specified return value condition. 29 | /// 30 | public MaybeNullWhenAttribute(bool returnValue) => 31 | ReturnValue = returnValue; 32 | } 33 | #else 34 | using System.Runtime.CompilerServices; 35 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute))] 36 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/MemberNotNullAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Targets = AttributeTargets; 9 | 10 | /// 11 | /// Specifies that the method or property will ensure that the listed field and property members have 12 | /// not- values. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: Targets.Method | 18 | Targets.Property, 19 | Inherited = false, 20 | AllowMultiple = true)] 21 | #if PolyPublic 22 | public 23 | #endif 24 | sealed class MemberNotNullAttribute : 25 | Attribute 26 | { 27 | /// 28 | /// Gets field or property member names. 29 | /// 30 | public string[] Members { get; } 31 | 32 | /// 33 | /// Initializes the attribute with a field or property member. 34 | /// 35 | public MemberNotNullAttribute(string member) => 36 | Members = [member]; 37 | 38 | /// 39 | /// Initializes the attribute with the list of field and property members. 40 | /// 41 | public MemberNotNullAttribute(params string[] members) => 42 | Members = members; 43 | } 44 | #else 45 | using System.Runtime.CompilerServices; 46 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MemberNotNullAttribute))] 47 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/MemberNotNullWhenAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Targets = AttributeTargets; 9 | 10 | /// 11 | /// Specifies that the method or property will ensure that the listed field and property members have 12 | /// non- values when returning with the specified return value condition. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: Targets.Method | 18 | Targets.Property, 19 | Inherited = false, 20 | AllowMultiple = true)] 21 | #if PolyPublic 22 | public 23 | #endif 24 | sealed class MemberNotNullWhenAttribute : 25 | Attribute 26 | { 27 | /// 28 | /// Gets the return value condition. 29 | /// 30 | public bool ReturnValue { get; } 31 | 32 | /// 33 | /// Gets field or property member names. 34 | /// 35 | public string[] Members { get; } 36 | 37 | /// 38 | /// Initializes the attribute with the specified return value condition and a field or property member. 39 | /// 40 | public MemberNotNullWhenAttribute(bool returnValue, string member) 41 | { 42 | ReturnValue = returnValue; 43 | Members = [member]; 44 | } 45 | 46 | /// 47 | /// Initializes the attribute with the specified return value condition and list 48 | /// of field and property members. 49 | /// 50 | public MemberNotNullWhenAttribute(bool returnValue, params string[] members) 51 | { 52 | ReturnValue = returnValue; 53 | Members = members; 54 | } 55 | } 56 | #else 57 | using System.Runtime.CompilerServices; 58 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute))] 59 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/NotNullAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Targets = AttributeTargets; 9 | 10 | /// 11 | /// Specifies that an output is not even if the 12 | /// corresponding type allows it. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: Targets.Field | 18 | Targets.Parameter | 19 | Targets.Property | 20 | Targets.ReturnValue)] 21 | #if PolyPublic 22 | public 23 | #endif 24 | sealed class NotNullAttribute : 25 | Attribute; 26 | #else 27 | using System.Runtime.CompilerServices; 28 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullAttribute))] 29 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Nullable/NotNullIfNotNullAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Targets = AttributeTargets; 9 | 10 | [ExcludeFromCodeCoverage] 11 | [DebuggerNonUserCode] 12 | [AttributeUsage( 13 | validOn: Targets.Parameter | 14 | Targets.Property | 15 | Targets.ReturnValue, 16 | AllowMultiple = true)] 17 | #if PolyPublic 18 | public 19 | #endif 20 | sealed class NotNullIfNotNullAttribute : 21 | Attribute 22 | { 23 | /// 24 | /// Gets the associated parameter name. 25 | /// The output will be non- if the argument to the 26 | /// parameter specified is non-. 27 | /// 28 | public string ParameterName { get; } 29 | 30 | /// 31 | /// Initializes the attribute with the associated parameter name. 32 | /// 33 | public NotNullIfNotNullAttribute(string parameterName) => 34 | ParameterName = parameterName; 35 | } 36 | #else 37 | using System.Runtime.CompilerServices; 38 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute))] 39 | #endif 40 | -------------------------------------------------------------------------------- /src/Polyfill/Nullable/NotNullWhenAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | /// 9 | /// Specifies that when a method returns , 10 | /// the parameter will not be even if the corresponding type allows it. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | [DebuggerNonUserCode] 14 | [AttributeUsage(AttributeTargets.Parameter)] 15 | #if PolyPublic 16 | public 17 | #endif 18 | sealed class NotNullWhenAttribute : 19 | Attribute 20 | { 21 | /// 22 | /// Gets the return value condition. 23 | /// If the method returns this value, the associated parameter will not be . 24 | /// 25 | public bool ReturnValue { get; } 26 | 27 | /// 28 | /// Initializes the attribute with the specified return value condition. 29 | /// 30 | public NotNullWhenAttribute(bool returnValue) => 31 | ReturnValue = returnValue; 32 | } 33 | #else 34 | using System.Runtime.CompilerServices; 35 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullWhenAttribute))] 36 | #endif -------------------------------------------------------------------------------- /src/Polyfill/OverloadResolutionPriorityAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET9_0_OR_GREATER 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Specifies the priority of a member in overload resolution. When unspecified, the default priority is 0. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | AttributeTargets.Method | 18 | AttributeTargets.Constructor | 19 | AttributeTargets.Property, 20 | Inherited = false)] 21 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.overloadresolutionpriorityattribute?view=net-10.0 22 | #if PolyPublic 23 | public 24 | #endif 25 | sealed class OverloadResolutionPriorityAttribute : 26 | Attribute 27 | { 28 | /// 29 | /// Initializes a new instance of the class. 30 | /// 31 | public OverloadResolutionPriorityAttribute(int priority) => Priority = priority; 32 | 33 | /// 34 | /// The priority of the member. 35 | /// 36 | public int Priority { get; } 37 | } 38 | #else 39 | using System.Runtime.CompilerServices; 40 | [assembly: TypeForwardedTo(typeof(OverloadResolutionPriorityAttribute))] 41 | #endif -------------------------------------------------------------------------------- /src/Polyfill/ParamCollectionAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET9_0_OR_GREATER 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Indicates that a method allows a variable number of arguments in its invocation. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.paramcollectionattribute?view=net-10.0 18 | #if PolyPublic 19 | public 20 | #endif 21 | sealed class ParamCollectionAttribute : Attribute; 22 | #else 23 | using System.Runtime.CompilerServices; 24 | [assembly: TypeForwardedTo(typeof(ParamCollectionAttribute))] 25 | #endif -------------------------------------------------------------------------------- /src/Polyfill/PlatformCompatibility/OSPlatformAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | namespace System.Runtime.Versioning; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Base type for all platform-specific API attributes. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | #if PolyPublic 17 | public 18 | #endif 19 | abstract class OSPlatformAttribute(string platformName) : 20 | Attribute 21 | { 22 | public string PlatformName { get; } = platformName; 23 | } 24 | #else 25 | using System.Runtime.CompilerServices; 26 | [assembly: TypeForwardedTo(typeof(System.Runtime.Versioning.OSPlatformAttribute))] 27 | #endif -------------------------------------------------------------------------------- /src/Polyfill/PlatformCompatibility/ObsoletedOSPlatformAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | #nullable enable 7 | 8 | namespace System.Runtime.Versioning; 9 | 10 | using Diagnostics; 11 | using Diagnostics.CodeAnalysis; 12 | 13 | using Targets = AttributeTargets; 14 | 15 | /// 16 | /// Marks APIs that were obsoleted in a given operating system version. 17 | /// 18 | [ExcludeFromCodeCoverage] 19 | [DebuggerNonUserCode] 20 | [AttributeUsage( 21 | validOn: Targets.Assembly | 22 | Targets.Class | 23 | Targets.Constructor | 24 | Targets.Enum | 25 | Targets.Event | 26 | Targets.Field | 27 | Targets.Interface | 28 | Targets.Method | 29 | Targets.Module | 30 | Targets.Property | 31 | Targets.Struct, 32 | AllowMultiple = true, 33 | Inherited = false)] 34 | #if PolyPublic 35 | public 36 | #endif 37 | sealed class ObsoletedOSPlatformAttribute : 38 | OSPlatformAttribute 39 | { 40 | public ObsoletedOSPlatformAttribute(string platformName) : 41 | base(platformName) 42 | { 43 | } 44 | 45 | public ObsoletedOSPlatformAttribute(string platformName, string? message) : 46 | base(platformName) => 47 | Message = message; 48 | 49 | public string? Message { get; } 50 | public string? Url { get; set; } 51 | } 52 | #else 53 | using System.Runtime.CompilerServices; 54 | [assembly: TypeForwardedTo(typeof(System.Runtime.Versioning.ObsoletedOSPlatformAttribute))] 55 | #endif -------------------------------------------------------------------------------- /src/Polyfill/PlatformCompatibility/SupportedOSPlatformAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Runtime.Versioning; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | using Targets = AttributeTargets; 12 | 13 | /// 14 | /// Records the operating system (and minimum version) that supports an API. Multiple attributes can be 15 | /// applied to indicate support on multiple operating systems. 16 | /// 17 | [ExcludeFromCodeCoverage] 18 | [DebuggerNonUserCode] 19 | [AttributeUsage( 20 | validOn: Targets.Assembly | 21 | Targets.Class | 22 | Targets.Constructor | 23 | Targets.Enum | 24 | Targets.Event | 25 | Targets.Field | 26 | Targets.Interface | 27 | Targets.Method | 28 | Targets.Module | 29 | Targets.Property | 30 | Targets.Struct, 31 | AllowMultiple = true, 32 | Inherited = false)] 33 | #if PolyPublic 34 | public 35 | #endif 36 | sealed class SupportedOSPlatformAttribute(string platformName) : 37 | OSPlatformAttribute(platformName); 38 | #else 39 | using System.Runtime.CompilerServices; 40 | [assembly: TypeForwardedTo(typeof(System.Runtime.Versioning.SupportedOSPlatformAttribute))] 41 | #endif -------------------------------------------------------------------------------- /src/Polyfill/PlatformCompatibility/SupportedOSPlatformGuardAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | namespace System.Runtime.Versioning; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | using Targets = AttributeTargets; 12 | 13 | /// 14 | /// Annotates a custom guard field, property or method with a supported platform name and optional version. 15 | /// Multiple attributes can be applied to indicate guard for multiple supported platforms. 16 | /// 17 | [ExcludeFromCodeCoverage] 18 | [DebuggerNonUserCode] 19 | [AttributeUsage( 20 | validOn: Targets.Field | 21 | Targets.Method | 22 | Targets.Property, 23 | AllowMultiple = true, 24 | Inherited = false)] 25 | #if PolyPublic 26 | public 27 | #endif 28 | sealed class SupportedOSPlatformGuardAttribute(string platformName) : 29 | OSPlatformAttribute(platformName); 30 | #else 31 | using System.Runtime.CompilerServices; 32 | [assembly: TypeForwardedTo(typeof(System.Runtime.Versioning.SupportedOSPlatformGuardAttribute))] 33 | #endif -------------------------------------------------------------------------------- /src/Polyfill/PlatformCompatibility/TargetPlatformAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Runtime.Versioning; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Records the platform that the project targeted. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage(AttributeTargets.Assembly)] 17 | #if PolyPublic 18 | public 19 | #endif 20 | sealed class TargetPlatformAttribute(string platformName) : 21 | OSPlatformAttribute(platformName); 22 | #else 23 | using System.Runtime.CompilerServices; 24 | [assembly: TypeForwardedTo(typeof(System.Runtime.Versioning.TargetPlatformAttribute))] 25 | #endif -------------------------------------------------------------------------------- /src/Polyfill/PlatformCompatibility/UnsupportedOSPlatformAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | #nullable enable 7 | 8 | namespace System.Runtime.Versioning; 9 | 10 | using Diagnostics; 11 | using Diagnostics.CodeAnalysis; 12 | 13 | using Targets = AttributeTargets; 14 | 15 | /// 16 | /// Marks APIs that were removed in a given operating system version. 17 | /// 18 | [ExcludeFromCodeCoverage] 19 | [DebuggerNonUserCode] 20 | [AttributeUsage( 21 | validOn: Targets.Assembly | 22 | Targets.Class | 23 | Targets.Constructor | 24 | Targets.Enum | 25 | Targets.Event | 26 | Targets.Field | 27 | Targets.Interface | 28 | Targets.Method | 29 | Targets.Module | 30 | Targets.Property | 31 | Targets.Struct, 32 | AllowMultiple = true, 33 | Inherited = false)] 34 | #if PolyPublic 35 | public 36 | #endif 37 | sealed class UnsupportedOSPlatformAttribute : 38 | OSPlatformAttribute 39 | { 40 | public UnsupportedOSPlatformAttribute(string platformName) : 41 | base(platformName) 42 | { 43 | } 44 | 45 | public UnsupportedOSPlatformAttribute(string platformName, string? message) : 46 | base(platformName) => 47 | Message = message; 48 | 49 | public string? Message { get; } 50 | } 51 | #else 52 | using System.Runtime.CompilerServices; 53 | [assembly: TypeForwardedTo(typeof(System.Runtime.Versioning.UnsupportedOSPlatformAttribute))] 54 | #endif -------------------------------------------------------------------------------- /src/Polyfill/PlatformCompatibility/UnsupportedOSPlatformGuardAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | #pragma warning disable 7 | 8 | namespace System.Runtime.Versioning; 9 | 10 | using Diagnostics; 11 | using Diagnostics.CodeAnalysis; 12 | 13 | using Targets = AttributeTargets; 14 | 15 | /// 16 | /// Annotates the custom guard field, property or method with an unsupported platform name and optional version. 17 | /// Multiple attributes can be applied to indicate guard for multiple unsupported platforms. 18 | /// 19 | [ExcludeFromCodeCoverage] 20 | [DebuggerNonUserCode] 21 | [AttributeUsage( 22 | validOn: Targets.Field | 23 | Targets.Method | 24 | Targets.Property, 25 | AllowMultiple = true, 26 | Inherited = false)] 27 | #if PolyPublic 28 | public 29 | #endif 30 | sealed class UnsupportedOSPlatformGuardAttribute(string platformName) : 31 | OSPlatformAttribute(platformName); 32 | #else 33 | using System.Runtime.CompilerServices; 34 | [assembly: TypeForwardedTo(typeof(System.Runtime.Versioning.UnsupportedOSPlatformGuardAttribute))] 35 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | global using global::Polyfills; 4 | 5 | namespace Polyfills; 6 | 7 | using System.ComponentModel; 8 | using System.Diagnostics; 9 | using System.Diagnostics.CodeAnalysis; 10 | 11 | [EditorBrowsable(EditorBrowsableState.Never)] 12 | [ExcludeFromCodeCoverage] 13 | [DebuggerNonUserCode] 14 | #if PolyPublic 15 | public 16 | #endif 17 | static partial class Polyfill; -------------------------------------------------------------------------------- /src/Polyfill/Polyfill.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | Polyfill.nuspec 5 | Source only packages that exposes newer .net and C# features to older runtimes. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | configuration=$(Configuration);version=$(PackageVersion);authors=$(Authors);projectUrl=$(PackageProjectUrl);description=$(Description);tags=$(PackageTags) 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Polyfill/Polyfill.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Polyfill 5 | $version$ 6 | $authors$ 7 | true 8 | MIT 9 | https://github.com/SimonCropp/Polyfill 10 | icon.png 11 | false 12 | $description$ 13 | $copyright$ 14 | $tags$ 15 | 16 | 17 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_CancellationTokenSource.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET8_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | static partial class Polyfill 12 | { 13 | /// Communicates a request for cancellation asynchronously. 14 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource.cancelasync?view=net-10.0 15 | public static Task CancelAsync(this CancellationTokenSource target) 16 | { 17 | if (target.IsCancellationRequested) 18 | { 19 | return Task.CompletedTask; 20 | } 21 | 22 | var task = Task.Run(target.Cancel); 23 | 24 | while (!target.IsCancellationRequested) ; 25 | 26 | return task; 27 | } 28 | } 29 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_ConcurrentBag.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Concurrent; 9 | 10 | static partial class Polyfill 11 | { 12 | /// 13 | /// Removes all values from the . 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentbag-1.clear?view=net-10.0 16 | public static void Clear(this ConcurrentBag target) 17 | { 18 | while (!target.IsEmpty) 19 | { 20 | target.TryTake(out _); 21 | } 22 | } 23 | } 24 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_ConcurrentDictionary.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP && !NETSTANDARD2_1_OR_GREATER && !NET472_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Collections.Concurrent; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Adds a key/value pair to the 15 | /// if the key does not already exist. 16 | /// 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2.getoradd?view=net-10.0#system-collections-concurrent-concurrentdictionary-2-getoradd-1(-0-system-func((-0-0-1))-0) 18 | public static TValue GetOrAdd(this ConcurrentDictionary target, TKey key, Func valueFactory, TArg factoryArgument) 19 | where TKey : notnull 20 | { 21 | while (true) 22 | { 23 | TValue value; 24 | if (target.TryGetValue(key, out value)) 25 | { 26 | return value; 27 | } 28 | 29 | value = valueFactory(key, factoryArgument); 30 | if (target.TryAdd(key, value)) 31 | { 32 | return value; 33 | } 34 | } 35 | } 36 | } 37 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_ConcurrentQueue.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP && !NETSTANDARD2_1_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Concurrent; 9 | 10 | static partial class Polyfill 11 | { 12 | /// 13 | /// Removes all values from the . 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentqueue-1.clear?view=net-10.0 16 | public static void Clear(this ConcurrentQueue target) 17 | { 18 | while (target.TryDequeue(out _)); 19 | } 20 | } 21 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_DateOnly.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if NET6_0 || NET7_0 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Collections.Generic; 10 | using System.ComponentModel; 11 | 12 | static partial class Polyfill 13 | { 14 | /// 15 | /// Deconstructs DateOnly by Year, Month, and Day. 16 | /// 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.dateonly.deconstruct?view=net-10.0 18 | [EditorBrowsable(EditorBrowsableState.Never)] 19 | public static void Deconstruct(this DateOnly target, out int year, out int month, out int day) 20 | { 21 | year = target.Year; 22 | month = target.Month; 23 | day = target.Day; 24 | } 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_DateTime.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | namespace Polyfills; 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | 11 | static partial class Polyfill 12 | { 13 | #if NET6_0 || NET7_0 14 | /// 15 | /// Deconstructs this instance by and . 16 | /// 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.datetime.deconstruct?view=net-10.0#system-datetime-deconstruct(system-dateonly@-system-timeonly@) 18 | [EditorBrowsable(EditorBrowsableState.Never)] 19 | public static void Deconstruct(this DateTime target, out DateOnly date, out TimeOnly time) 20 | { 21 | date = DateOnly.FromDateTime(target); 22 | time = TimeOnly.FromDateTime(target); 23 | } 24 | #endif 25 | 26 | #if !NET8_0_OR_GREATER 27 | /// 28 | /// Deconstructs by , and . 29 | /// 30 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.datetime.deconstruct?view=net-10.0#system-datetime-deconstruct(system-int32@-system-int32@-system-int32@) 31 | [EditorBrowsable(EditorBrowsableState.Never)] 32 | public static void Deconstruct(this DateTime target, out int year, out int month, out int day) 33 | { 34 | year = target.Year; 35 | month = target.Month; 36 | day = target.Day; 37 | } 38 | #endif 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_DateTimeOffset.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if NET6_0 || NET7_0 5 | namespace Polyfills; 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Deconstructs this instance by , , and . 15 | /// 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset.deconstruct?view=net-10.0 17 | [EditorBrowsable(EditorBrowsableState.Never)] 18 | public static void Deconstruct(this DateTimeOffset target, out DateOnly date, out TimeOnly time, out TimeSpan offset) 19 | { 20 | date = DateOnly.FromDateTime(target.DateTime); 21 | time = TimeOnly.FromDateTime(target.DateTime); 22 | 23 | offset = target.Offset; 24 | } 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_DefaultInterpolatedStringHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if FeatureMemory && NET6_0_OR_GREATER && !NET10_0_OR_GREATER 5 | namespace Polyfills; 6 | 7 | using System.Runtime.CompilerServices; 8 | 9 | static partial class Polyfill 10 | { 11 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.defaultinterpolatedstringhandler.clear?view=net-10.0 12 | public static void Clear(this DefaultInterpolatedStringHandler target) => 13 | target.ToStringAndClear(); 14 | } 15 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Delegate.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | namespace Polyfills; 6 | 7 | using System; 8 | using System.Collections.Concurrent; 9 | using System.Runtime.CompilerServices; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Gets a value that indicates whether the Delegate has a single invocation target. 15 | /// 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.delegate.hassingletarget?view=net-10.0 17 | public static bool HasSingleTarget(this Delegate target) => 18 | #if NET9_0_OR_GREATER 19 | target.HasSingleTarget; 20 | #else 21 | target.GetInvocationList().Length == 1; 22 | #endif 23 | } 24 | -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_DictionaryEntry.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if !NETCOREAPP && !NETSTANDARD2_1_OR_GREATER 6 | 7 | namespace Polyfills; 8 | 9 | using System; 10 | using System.Collections; 11 | using System.ComponentModel; 12 | 13 | static partial class Polyfill 14 | { 15 | /// 16 | /// Deconstructs the current . 17 | /// 18 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.dictionaryentry.deconstruct?view=net-10.0#system-collections-dictionaryentry-deconstruct(system-object@-system-object@) 19 | [EditorBrowsable(EditorBrowsableState.Never)] 20 | public static void Deconstruct(this DictionaryEntry target, out object key, out object? value) 21 | { 22 | key = target.Key; 23 | value = target.Value; 24 | } 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Encoding_GetByteCount.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if FeatureMemory 6 | 7 | namespace Polyfills; 8 | 9 | using System; 10 | using System.Runtime.InteropServices; 11 | using System.Text; 12 | 13 | static partial class Polyfill 14 | { 15 | #if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 16 | /// 17 | /// Calculates the number of bytes produced by encoding the characters in the specified character span. 18 | /// 19 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getbytecount?view=net-10.0#system-text-encoding-getbytecount(system-readonlyspan((system-char))) 20 | #if AllowUnsafeBlocks 21 | public unsafe static int GetByteCount(this Encoding target, ReadOnlySpan chars) 22 | { 23 | fixed (char* charsPtr = chars) 24 | { 25 | return target.GetByteCount(charsPtr, chars.Length); 26 | } 27 | } 28 | #else 29 | public static int GetByteCount(this Encoding target, ReadOnlySpan chars) => 30 | target.GetByteCount(chars.ToArray()); 31 | #endif 32 | #endif 33 | 34 | } 35 | 36 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Encoding_GetCharCount.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if FeatureMemory 6 | 7 | namespace Polyfills; 8 | 9 | using System; 10 | using System.Runtime.InteropServices; 11 | using System.Text; 12 | 13 | static partial class Polyfill 14 | { 15 | #if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 16 | /// 17 | /// Calculates the number of characters produced by decoding the provided read-only byte span. 18 | /// 19 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getcharcount?view=net-10.0#system-text-encoding-getcharcount(system-readonlyspan((system-byte))) 20 | #if AllowUnsafeBlocks 21 | public static unsafe int GetCharCount(this Encoding target, ReadOnlySpan bytes) 22 | { 23 | fixed (byte* bytesPtr = bytes) 24 | { 25 | return target.GetCharCount(bytesPtr, bytes.Length); 26 | } 27 | } 28 | #else 29 | public static int GetCharCount(this Encoding target, ReadOnlySpan bytes) => 30 | target.GetCharCount(bytes.ToArray()); 31 | #endif 32 | #endif 33 | 34 | } 35 | 36 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Encoding_GetChars.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if FeatureMemory 6 | 7 | namespace Polyfills; 8 | 9 | using System; 10 | using System.Runtime.InteropServices; 11 | using System.Text; 12 | 13 | static partial class Polyfill 14 | { 15 | #if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER 16 | /// 17 | /// Decodes all the bytes in the specified read-only byte span into a character span. 18 | /// 19 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getchars?view=net-10.0#system-text-encoding-getchars(system-readonlyspan((system-byte))-system-span((system-char))) 20 | #if AllowUnsafeBlocks 21 | public static unsafe int GetChars(this Encoding target, ReadOnlySpan bytes, Span chars) 22 | { 23 | fixed (byte* bytesPtr = bytes) 24 | fixed (char* charsPtr = chars) 25 | { 26 | return target.GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length); 27 | } 28 | } 29 | #else 30 | public static int GetChars(this Encoding target, ReadOnlySpan bytes, Span chars) 31 | { 32 | var charArray = new char[bytes.Length]; 33 | var array = bytes.ToArray(); 34 | var count = target.GetChars(array, 0, bytes.Length, charArray, 0); 35 | new ReadOnlySpan(charArray).CopyTo(chars); 36 | return count; 37 | } 38 | #endif 39 | #endif 40 | 41 | } 42 | 43 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Encoding_TryGet.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if FeatureMemory 6 | 7 | namespace Polyfills; 8 | 9 | using System; 10 | using System.Runtime.InteropServices; 11 | using System.Text; 12 | 13 | static partial class Polyfill 14 | { 15 | #if !NET8_0_OR_GREATER 16 | 17 | /// Decodes into a span of chars a set of bytes from the specified read-only span if the destination is large enough. 18 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.trygetchars?view=net-10.0 19 | public static bool TryGetChars(this Encoding target, ReadOnlySpan bytes, Span chars, out int charsWritten) 20 | { 21 | int required = target.GetCharCount(bytes); 22 | if (required <= chars.Length) 23 | { 24 | charsWritten = target.GetChars(bytes, chars); 25 | return true; 26 | } 27 | 28 | charsWritten = 0; 29 | return false; 30 | } 31 | 32 | /// Encodes into a span of bytes a set of characters from the specified read-only span if the destination is large enough. 33 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.trygetbytes?view=net-10.0 34 | public static bool TryGetBytes(this Encoding target, ReadOnlySpan chars, Span bytes, out int bytesWritten) 35 | { 36 | int required = target.GetByteCount(chars); 37 | if (required <= bytes.Length) 38 | { 39 | bytesWritten = target.GetBytes(chars, bytes); 40 | return true; 41 | } 42 | 43 | bytesWritten = 0; 44 | return false; 45 | } 46 | #endif 47 | } 48 | 49 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_Append.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if NET46X || NET47 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | 10 | static partial class Polyfill 11 | { 12 | /// 13 | /// Appends a value to the end of the sequence. 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.append?view=net-10.0 16 | public static IEnumerable Append( 17 | this IEnumerable target, 18 | TSource element) 19 | { 20 | foreach (var item in target) 21 | { 22 | yield return item; 23 | } 24 | 25 | yield return element; 26 | } 27 | } 28 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_DistinctBy.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Collections.Generic; 10 | 11 | static partial class Polyfill 12 | { 13 | 14 | /// Returns distinct elements from a sequence according to a specified key selector function. 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinctby?view=net-10.0#system-linq-enumerable-distinctby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1))) 16 | public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector) => 17 | DistinctBy(source, keySelector, null); 18 | 19 | /// Returns distinct elements from a sequence according to a specified key selector function. 20 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinctby?view=net-10.0#system-linq-enumerable-distinctby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1))) 21 | public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector, IEqualityComparer comparer) 22 | { 23 | using var enumerator = source.GetEnumerator(); 24 | 25 | if (!enumerator.MoveNext()) 26 | { 27 | yield break; 28 | } 29 | 30 | var set = new HashSet(comparer); 31 | do 32 | { 33 | var element = enumerator.Current; 34 | if (set.Add(keySelector(element))) 35 | { 36 | yield return element; 37 | } 38 | } 39 | while (enumerator.MoveNext()); 40 | } 41 | } 42 | 43 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_Index.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET9_0_OR_GREATER && FeatureValueTuple 5 | namespace Polyfills; 6 | 7 | using System.Collections.Generic; 8 | 9 | static partial class Polyfill 10 | { 11 | /// 12 | /// https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-9/overview#linq 13 | /// 14 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.index?view=net-10.0#system-linq-enumerable-index-1(system-collections-generic-ienumerable((-0))) 15 | public static IEnumerable<(int Index, TSource Item)> Index(this IEnumerable source) 16 | { 17 | var index = 0; 18 | foreach (var item in source) 19 | { 20 | yield return (index, item); 21 | index++; 22 | } 23 | } 24 | } 25 | 26 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_Max.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | 10 | static partial class Polyfill 11 | { 12 | /// Returns the maximum value in a generic sequence. 13 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.max?view=net-10.0#system-linq-enumerable-max-1(system-collections-generic-ienumerable((-0))-system-collections-generic-icomparer((-0))) 14 | public static TSource? Max( 15 | this IEnumerable source, 16 | IComparer? comparer) => 17 | source 18 | .MaxBy(_ => _, comparer); 19 | } 20 | 21 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_Min.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | 10 | static partial class Polyfill 11 | { 12 | /// Returns the minimum value in a generic sequence. 13 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.min?view=net-10.0#system-linq-enumerable-min-1(system-collections-generic-ienumerable((-0))-system-collections-generic-icomparer((-0))) 14 | public static TSource? Min( 15 | this IEnumerable source, 16 | IComparer? comparer) => 17 | source 18 | .MinBy(_ => _, comparer); 19 | } 20 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_SkipLast.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if NETFRAMEWORK || NETSTANDARD2_0 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Returns a new enumerable collection that contains the elements from source with the last count elements of the 15 | /// source collection omitted. 16 | /// 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.skiplast?view=net-10.0 18 | public static IEnumerable SkipLast( 19 | this IEnumerable target, 20 | int count) => 21 | target.Reverse().Skip(count).Reverse(); 22 | } 23 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_TakeLast.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | // Licensed to the .NET Foundation under one or more agreements. 5 | // The .NET Foundation licenses this file to you under the MIT license. 6 | 7 | 8 | #if NETSTANDARD2_0 || NETFRAMEWORK 9 | 10 | namespace Polyfills; 11 | 12 | using System.Collections.Generic; 13 | 14 | static partial class Polyfill 15 | { 16 | /// 17 | /// Returns a new enumerable collection that contains the last count elements from source. 18 | /// 19 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.takelast?view=net-10.0 20 | public static IEnumerable TakeLast(this IEnumerable source, int count) 21 | { 22 | if (count <= 0 || IsEmptyArray(source)) 23 | { 24 | return []; 25 | } 26 | 27 | return TakeRangeFromEndIterator( 28 | source, 29 | isStartIndexFromEnd: true, startIndex: count, 30 | isEndIndexFromEnd: true, endIndex: 0); 31 | } 32 | } 33 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_ThrowHelper.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | namespace Polyfills; 5 | 6 | static partial class Polyfill 7 | { 8 | static void ThrowNoElementsException() => 9 | throw new System.InvalidOperationException("Sequence contains no elements"); 10 | } 11 | -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_ToHashSet.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if NET471 || NET46X || NETSTANDARD2_0 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | 10 | static partial class Polyfill 11 | { 12 | /// 13 | /// Creates a HashSet from an IEnumerable using the comparer to compare keys. 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.tohashset?view=net-10.0#system-linq-enumerable-tohashset-1(system-collections-generic-ienumerable((-0))-system-collections-generic-iequalitycomparer((-0))) 16 | public static HashSet ToHashSet( 17 | this IEnumerable target, 18 | IEqualityComparer? comparer = null) => 19 | new(target, comparer); 20 | 21 | } 22 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_TryGetNonEnumeratedCount.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections; 9 | using System.Collections.Generic; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Attempts to determine the number of elements in a sequence without forcing an enumeration. 15 | /// 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.trygetnonenumeratedcount?view=net-10.0 17 | public static bool TryGetNonEnumeratedCount(this IEnumerable target, out int count) 18 | { 19 | if (target is ICollection genericCollection) 20 | { 21 | count = genericCollection.Count; 22 | return true; 23 | } 24 | 25 | if (target is ICollection collection) 26 | { 27 | count = collection.Count; 28 | return true; 29 | } 30 | 31 | count = 0; 32 | return false; 33 | } 34 | } 35 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IEnumerable_Zip.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if FeatureValueTuple 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | 10 | static partial class Polyfill 11 | { 12 | #if !NET6_0_OR_GREATER 13 | 14 | /// 15 | /// Produces a sequence of tuples with elements from the three specified sequences. 16 | /// 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.zip?view=net-10.0#system-linq-enumerable-zip-3(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-collections-generic-ienumerable((-2))) 18 | public static IEnumerable<(TFirst First, TSecond Second, TThird Third)> Zip(this IEnumerable first, IEnumerable second, IEnumerable third) 19 | { 20 | using var e1 = first.GetEnumerator(); 21 | using var e2 = second.GetEnumerator(); 22 | using var e3 = third.GetEnumerator(); 23 | while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext()) 24 | { 25 | yield return (e1.Current, e2.Current, e3.Current); 26 | } 27 | } 28 | #endif 29 | 30 | #if !NETCOREAPP3_1_OR_GREATER 31 | 32 | /// 33 | /// Produces a sequence of tuples with elements from the two specified sequences. 34 | /// 35 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.zip?view=net-10.0#system-linq-enumerable-zip-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))) 36 | public static IEnumerable<(TFirst First, TSecond Second)> Zip(this IEnumerable first, IEnumerable second) 37 | { 38 | using var e1 = first.GetEnumerator(); 39 | using var e2 = second.GetEnumerator(); 40 | while (e1.MoveNext() && e2.MoveNext()) 41 | { 42 | yield return (e1.Current, e2.Current); 43 | } 44 | } 45 | 46 | #endif 47 | 48 | } 49 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_IReadOnlyDictionary.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if NETFRAMEWORK || NETSTANDARD2_0 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | 10 | static partial class Polyfill 11 | { 12 | /// 13 | /// Tries to get the value associated with the specified key in the dictionary. 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.collectionextensions.getvalueordefault?view=net-10.0#system-collections-generic-collectionextensions-getvalueordefault-2(system-collections-generic-ireadonlydictionary((-0-1))-0-1) 16 | public static TValue GetValueOrDefault( 17 | this IReadOnlyDictionary target, 18 | TKey key, 19 | TValue defaultValue = default!) 20 | where TKey : notnull 21 | { 22 | if (target.TryGetValue(key, out var result)) 23 | { 24 | return result!; 25 | } 26 | 27 | return defaultValue; 28 | } 29 | } 30 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_KeyValuePair.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if !NETCOREAPP && !NETSTANDARD2_1_OR_GREATER 6 | 7 | namespace Polyfills; 8 | 9 | using System; 10 | using System.Collections.Generic; 11 | using System.ComponentModel; 12 | 13 | static partial class Polyfill 14 | { 15 | /// 16 | /// Deconstructs the current 17 | /// 18 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.keyvaluepair-2.deconstruct?view=net-10.0 19 | [EditorBrowsable(EditorBrowsableState.Never)] 20 | public static void Deconstruct( 21 | this KeyValuePair target, 22 | out TKey key, 23 | out TValue value) 24 | { 25 | key = target.Key; 26 | value = target.Value; 27 | } 28 | } 29 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Memory_IndexOf.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if FeatureMemory 6 | 7 | namespace Polyfills; 8 | 9 | using System; 10 | using System.Runtime.CompilerServices; 11 | using System.Buffers; 12 | using System.Collections.Generic; 13 | 14 | static partial class Polyfill 15 | { 16 | #if NET8_0_OR_GREATER && !NET10_0_OR_GREATER 17 | 18 | /// 19 | /// Searches for the specified value and returns the index of its first occurrence. If not found, returns -1. Values are compared using IEquatable{T}.Equals(T). 20 | /// 21 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.indexof?view=net-10.0#system-memoryextensions-indexof-1(system-readonlyspan((-0))-0-system-collections-generic-iequalitycomparer((-0))) 22 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 | public static int IndexOf(this ReadOnlySpan span, T value, IEqualityComparer? comparer = null) 24 | { 25 | comparer ??= EqualityComparer.Default; 26 | for (var i = 0; i < span.Length; i++) 27 | { 28 | if (comparer.Equals(span[i], value)) 29 | { 30 | return i; 31 | } 32 | } 33 | 34 | return -1; 35 | } 36 | 37 | #endif 38 | } 39 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Memory_IndexOfAny.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if FeatureMemory && NET8_0_OR_GREATER && !NET10_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Collections.Generic; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Searches for the first index of any of the specified values similar to calling IndexOf several times with the logical OR operator. If not found, returns -1. 15 | /// 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.countany?view=net-10.0#system-memoryextensions-countany-1(system-readonlyspan((-0))-system-buffers-searchvalues((-0))) 17 | public static int IndexOfAny(this ReadOnlySpan span, ReadOnlySpan values, IEqualityComparer? comparer = default) 18 | { 19 | comparer ??= EqualityComparer.Default; 20 | 21 | for (var i = 0; i < span.Length; i++) 22 | { 23 | if (values.Contains(span[i], comparer)) 24 | { 25 | return i; 26 | } 27 | } 28 | 29 | return -1; 30 | } 31 | } 32 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Memory_SpanSplitEnumeratorMode.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if FeatureMemory && !NET9_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | static partial class Polyfill 9 | { 10 | /// Indicates in which mode is operating, with regards to how it should interpret its state. 11 | enum SpanSplitEnumeratorMode 12 | { 13 | /// Either a default was used, or the enumerator has finished enumerating and there's no more work to do. 14 | None = 0, 15 | 16 | /// A single T separator was provided. 17 | SingleElement, 18 | 19 | /// A span of separators was provided, each of which should be treated independently. 20 | Any, 21 | 22 | /// The separator is a span of elements to be treated as a single sequence. 23 | Sequence, 24 | 25 | /// The separator is an empty sequence, such that no splits should be performed. 26 | EmptySequence, 27 | 28 | #if NET8_0 29 | /// 30 | /// A was provided and should behave the same as with but with the separators in the 31 | /// instance instead of in a . 32 | /// 33 | SearchValues 34 | #endif 35 | } 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_MethodInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Reflection; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Creates a delegate of type T with the specified target from this method. 15 | /// 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/System.Reflection.MethodInfo.CreateDelegate?view=net-10.0#system-reflection-methodinfo-createdelegate-1 17 | public static T CreateDelegate(this MethodInfo method) where T : Delegate => (T)method.CreateDelegate(typeof(T)); 18 | 19 | /// 20 | /// Creates a delegate of type T with the specified target from this method. 21 | /// 22 | //Link: https://learn.microsoft.com/en-us/dotnet/api/System.Reflection.MethodInfo.CreateDelegate?view=net-10.0#system-reflection-methodinfo-createdelegate-1(system-object) 23 | public static T CreateDelegate(this MethodInfo method, object? target) where T : Delegate => (T)method.CreateDelegate(typeof(T), target); 24 | } 25 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_MicroNanosecondAdd.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | 10 | static partial class Polyfill 11 | { 12 | /// 13 | /// Returns a new object that adds a specified number of microseconds to the value of this instance.. 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.datetime.addmicroseconds?view=net-10.0 16 | public static DateTime AddMicroseconds(this DateTime target, double microseconds) => 17 | target.AddMilliseconds(microseconds / 1000); 18 | 19 | /// 20 | /// Returns a new object that adds a specified number of microseconds to the value of this instance.. 21 | /// 22 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset.addmicroseconds?view=net-10.0 23 | public static DateTimeOffset AddMicroseconds(this DateTimeOffset target, double microseconds) => 24 | target.AddMilliseconds(microseconds / 1000); 25 | } 26 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_OrderedDictionary.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if NET9_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | using System.Diagnostics.CodeAnalysis; 10 | 11 | //TODO: fix links and docs 12 | static partial class Polyfill 13 | { 14 | //Link: https://github.com/dotnet/core/blob/main/release-notes/10.0/preview/preview1/libraries.md#additional-tryadd-and-trygetvalue-overloads-for-ordereddictionarytkey-tvalue?view=net-10.0 15 | public static bool TryAdd(this OrderedDictionary target, TKey key, TValue value, out int index) 16 | where TKey : notnull 17 | { 18 | var result = target.TryAdd(key, value); 19 | index = target.IndexOf(key); 20 | return result; 21 | } 22 | 23 | //Link: https://github.com/dotnet/core/blob/main/release-notes/10.0/preview/preview1/libraries.md#additional-tryadd-and-trygetvalue-overloads-for-ordereddictionarytkey-tvalue?view=net-10.0 24 | public static bool TryGetValue(this OrderedDictionary target, TKey key, [MaybeNullWhen(false)] out TValue value, out int index) 25 | where TKey : notnull 26 | { 27 | index = target.IndexOf(key); 28 | return target.TryGetValue(key, out value); 29 | } 30 | } 31 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Process.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Diagnostics; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | 13 | static partial class Polyfill 14 | { 15 | /// 16 | /// Instructs the Process component to wait for the associated process to exit, or 17 | /// for the to be canceled. 18 | /// 19 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexitasync?view=net-10.0 20 | public static async Task WaitForExitAsync(this Process target, CancellationToken cancellationToken = default) 21 | { 22 | if (!target.HasExited) 23 | { 24 | cancellationToken.ThrowIfCancellationRequested(); 25 | } 26 | 27 | try 28 | { 29 | target.EnableRaisingEvents = true; 30 | } 31 | catch (InvalidOperationException) 32 | { 33 | if (target.HasExited) 34 | { 35 | return; 36 | } 37 | 38 | throw; 39 | } 40 | 41 | var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); 42 | 43 | EventHandler handler = (_, _) => tcs.TrySetResult(null); 44 | target.Exited += handler; 45 | 46 | try 47 | { 48 | if (!target.HasExited) 49 | { 50 | using (cancellationToken.UnsafeRegister(static (s, cancellationToken) => ((TaskCompletionSource) s!).TrySetCanceled(cancellationToken), tcs)) 51 | { 52 | await tcs.Task.ConfigureAwait(false); 53 | } 54 | } 55 | } 56 | finally 57 | { 58 | target.Exited -= handler; 59 | } 60 | } 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Queue.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | namespace Polyfills; 6 | 7 | using System.Collections.Generic; 8 | using System.Diagnostics.CodeAnalysis; 9 | 10 | static partial class Polyfill 11 | { 12 | #if !NET6_0_OR_GREATER 13 | 14 | /// 15 | /// Ensures that the capacity of this queue is at least the specified capacity. If the current capacity is less than capacity, it is increased to at least the specified capacity. 16 | /// 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1.ensurecapacity?view=net-10.0#system-collections-generic-queue-1-ensurecapacity(system-int32) 18 | public static void EnsureCapacity(this Queue target, int capacity) 19 | { 20 | } 21 | 22 | #endif 23 | 24 | #if !NET9_0_OR_GREATER 25 | 26 | /// 27 | /// Sets the capacity of a Queue object to the specified number of entries. 28 | /// 29 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1.trimexcess?view=net-10.0#system-collections-generic-queue-1-trimexcess(system-int32) 30 | public static void TrimExcess(this Queue target, int capacity) 31 | { 32 | } 33 | 34 | #endif 35 | } -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Set.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | #pragma warning disable 4 | 5 | #if NET9_0 6 | 7 | namespace Polyfills; 8 | 9 | using System; 10 | using System.Diagnostics; 11 | using System.Collections.Generic; 12 | using System.Collections.ObjectModel; 13 | 14 | static partial class Polyfill 15 | { 16 | /// 17 | /// Returns a read-only wrapper for the specified set. 18 | /// 19 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.collectionextensions.asreadonly?view=net-10.0#system-collections-generic-collectionextensions-asreadonly-1(system-collections-generic-iset((-0))) 20 | public static ReadOnlySet AsReadOnly(this ISet target) => new(target); 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_SortedList.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | namespace Polyfills; 7 | 8 | using System.Collections.Generic; 9 | 10 | static partial class Polyfill 11 | { 12 | /// 13 | /// Gets the key corresponding to the specified index. 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.sortedlist-2.getkeyatindex?view=net-10.0 16 | public static TKey GetKeyAtIndex( 17 | this SortedList target, int index) => 18 | target.Keys[index]; 19 | 20 | /// 21 | /// Gets the value corresponding to the specified index. 22 | /// 23 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.sortedlist-2.getvalueatindex?view=net-10.0 24 | public static TValue GetValueAtIndex( 25 | this SortedList target, int index) => 26 | target.Values[index]; 27 | } 28 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_Stream_DisposeAsync.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP3_0_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && FeatureValueTask 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.IO; 10 | using System.Threading.Tasks; 11 | 12 | static partial class Polyfill 13 | { 14 | //https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs#L174 15 | /// 16 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously. 17 | /// 18 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.io.stream.disposeasync?view=net-10.0 19 | public static ValueTask DisposeAsync(this Stream target) 20 | { 21 | try 22 | { 23 | target.Dispose(); 24 | return default; 25 | } 26 | catch (Exception exception) 27 | { 28 | return new ValueTask(Task.FromException(exception)); 29 | } 30 | } 31 | } 32 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_StringBuilder.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if FeatureMemory && (!NETSTANDARD2_1_OR_GREATER && !NETCOREAPP2_1_OR_GREATER) 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Text; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Returns a value indicating whether the characters in this instance are equal to the characters in a specified 15 | /// read-only character span. 16 | /// 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.equals?view=net-10.0#system-text-stringbuilder-equals(system-readonlyspan((system-char))) 18 | public static bool Equals(this StringBuilder target, ReadOnlySpan span) 19 | { 20 | if (target.Length != span.Length) 21 | { 22 | return false; 23 | } 24 | 25 | for (var index = 0; index < target.Length; index++) 26 | { 27 | var ch1 = target[index]; 28 | var ch2 = span[index]; 29 | if (ch1 != ch2) 30 | { 31 | return false; 32 | } 33 | } 34 | 35 | return true; 36 | } 37 | } 38 | 39 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_StringBuilder_CopyTo.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if FeatureMemory && (!NETSTANDARD2_1_OR_GREATER && !NETCOREAPP2_1_OR_GREATER) 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Text; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Copies the characters from a specified segment of this instance to a destination Char span. 15 | /// 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.copyto?view=net-10.0#system-text-stringbuilder-copyto(system-int32-system-span((system-char))-system-int32) 17 | public static void CopyTo( 18 | this StringBuilder target, 19 | int sourceIndex, 20 | Span destination, 21 | int count) 22 | { 23 | var destinationIndex = 0; 24 | while (true) 25 | { 26 | if (sourceIndex == target.Length) 27 | { 28 | break; 29 | } 30 | 31 | if (destinationIndex == count) 32 | { 33 | break; 34 | } 35 | 36 | destination[destinationIndex] = target[sourceIndex]; 37 | destinationIndex++; 38 | sourceIndex++; 39 | } 40 | } 41 | } 42 | 43 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_StringBuilder_Insert.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && FeatureMemory 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Text; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Inserts the sequence of characters into this instance at the specified character position. 15 | /// 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.insert?view=net-10.0#system-text-stringbuilder-insert(system-int32-system-readonlyspan((system-char))) 17 | public static StringBuilder Insert(this StringBuilder target, int index, ReadOnlySpan value) => 18 | target.Insert(index, value.ToString()); 19 | } 20 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_StringBuilder_Replace.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET9_0_OR_GREATER && FeatureMemory 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Text; 10 | 11 | static partial class Polyfill 12 | { 13 | /// 14 | /// Replaces all instances of one string with another in part of this builder. 15 | /// 16 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.replace?view=net-10.0#system-text-stringbuilder-replace(system-readonlyspan((system-char))-system-readonlyspan((system-char))) 17 | public static StringBuilder Replace(this StringBuilder target, ReadOnlySpan oldValue, ReadOnlySpan newValue) => 18 | target.Replace(oldValue.ToString(), newValue.ToString()); 19 | 20 | /// 21 | /// Replaces all instances of one read-only character span with another in part of this builder. 22 | /// 23 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.replace?view=net-10.0#system-text-stringbuilder-replace(system-char-system-char-system-int32-system-int32) 24 | public static StringBuilder Replace(this StringBuilder target, ReadOnlySpan oldValue, ReadOnlySpan newValue, int startIndex, int count) => 25 | target.Replace(oldValue.ToString(), newValue.ToString(), startIndex, count); 26 | } 27 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Polyfill_TaskCompletionSource.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace Polyfills; 7 | 8 | using System; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | static partial class Polyfill 13 | { 14 | /// 15 | /// Transitions the underlying into the state 16 | /// using the specified token. 17 | /// 18 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1.setcanceled?view=net-10.0#system-threading-tasks-taskcompletionsource-1-setcanceled(system-threading-cancellationtoken) 19 | public static void SetCanceled( 20 | this TaskCompletionSource target, 21 | CancellationToken cancellationToken) 22 | { 23 | if (target.TrySetCanceled(cancellationToken)) 24 | { 25 | return; 26 | } 27 | 28 | throw new InvalidOperationException("An attempt was made to transition a task to a final state when it had already completed."); 29 | } 30 | } 31 | #endif -------------------------------------------------------------------------------- /src/Polyfill/RandomPolyfill.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | namespace Polyfills; 5 | 6 | using System; 7 | using System.Diagnostics; 8 | using System.Threading; 9 | using System.Diagnostics.CodeAnalysis; 10 | 11 | [ExcludeFromCodeCoverage] 12 | [DebuggerNonUserCode] 13 | #if PolyPublic 14 | public 15 | #endif 16 | static partial class RandomPolyfill 17 | { 18 | /// 19 | /// Provides a thread-safe Random instance that may be used concurrently from any thread. 20 | /// 21 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.random.shared?view=net-10.0 22 | public static Random Shared { get; } = 23 | #if NET6_0_OR_GREATER 24 | Random.Shared; 25 | #else 26 | new ThreadSafeRandom(); 27 | 28 | class ThreadSafeRandom : Random 29 | { 30 | Lock locker = new(); 31 | 32 | public override int Next() 33 | { 34 | lock (locker) 35 | return base.Next(); 36 | } 37 | 38 | public override int Next(int maxValue) 39 | { 40 | lock (locker) 41 | return base.Next(maxValue); 42 | } 43 | 44 | public override int Next(int minValue, int maxValue) 45 | { 46 | lock (locker) 47 | return base.Next(minValue, maxValue); 48 | } 49 | 50 | public override void NextBytes(byte[] buffer) 51 | { 52 | lock (locker) 53 | base.NextBytes(buffer); 54 | } 55 | 56 | public override double NextDouble() 57 | { 58 | lock (locker) 59 | return base.NextDouble(); 60 | } 61 | 62 | protected override double Sample() 63 | { 64 | lock (locker) 65 | return base.Sample(); 66 | } 67 | } 68 | #endif 69 | } -------------------------------------------------------------------------------- /src/Polyfill/Regex/ValueMatch.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | // Licensed to the .NET Foundation under one or more agreements. 4 | // The .NET Foundation licenses this file to you under the MIT license. 5 | 6 | #if FeatureMemory 7 | #if !NET7_0_OR_GREATER 8 | 9 | namespace System.Text.RegularExpressions; 10 | 11 | using System.Diagnostics; 12 | using System.Diagnostics.CodeAnalysis; 13 | 14 | /// 15 | /// Represents the results from a single regular expression match. 16 | /// 17 | [ExcludeFromCodeCoverage] 18 | [DebuggerNonUserCode] 19 | #if PolyPublic 20 | public 21 | #endif 22 | readonly ref struct ValueMatch 23 | { 24 | /// 25 | /// Crates an instance of the type based on the passed in and . 26 | /// 27 | internal ValueMatch(int index, int length) 28 | { 29 | Index = index; 30 | Length = length; 31 | } 32 | 33 | /// 34 | /// Gets the position in the original span where the first character of the captured sliced span is found. 35 | /// 36 | public int Index { get; } 37 | 38 | /// 39 | /// Gets the length of the captured sliced span. 40 | /// 41 | public int Length { get; } 42 | } 43 | #else 44 | using System.Runtime.CompilerServices; 45 | [assembly: TypeForwardedTo(typeof(System.Text.RegularExpressions.ValueMatch))] 46 | #endif 47 | #endif -------------------------------------------------------------------------------- /src/Polyfill/RequiredMemberAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using System.Diagnostics; 9 | using System.Diagnostics.CodeAnalysis; 10 | 11 | using Targets = AttributeTargets; 12 | 13 | /// 14 | /// Specifies that a type has required members or that a member is required. 15 | /// 16 | [ExcludeFromCodeCoverage] 17 | [DebuggerNonUserCode] 18 | [AttributeUsage( 19 | validOn: Targets.Class | 20 | Targets.Struct | 21 | Targets.Field | 22 | Targets.Property, 23 | Inherited = false)] 24 | #if PolyPublic 25 | public 26 | #endif 27 | sealed class RequiredMemberAttribute : 28 | Attribute; 29 | 30 | #else 31 | using System.Runtime.CompilerServices; 32 | [assembly: TypeForwardedTo(typeof(RequiredMemberAttribute))] 33 | #endif -------------------------------------------------------------------------------- /src/Polyfill/ResolveHttpGlobalProblem.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if NETFRAMEWORK 5 | 6 | using System.ComponentModel; 7 | using System.Diagnostics; 8 | using System.Diagnostics.CodeAnalysis; 9 | 10 | namespace System.Net.Http; 11 | 12 | [EditorBrowsable(EditorBrowsableState.Never)] 13 | [ExcludeFromCodeCoverage] 14 | [DebuggerNonUserCode] 15 | static class ResolveHttpGlobalProblem; 16 | 17 | #endif -------------------------------------------------------------------------------- /src/Polyfill/SetsRequiredMembersAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | /// 9 | /// Specifies that this constructor sets all required members for the current type, and callers 10 | /// do not need to set any required members themselves. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | [DebuggerNonUserCode] 14 | [AttributeUsage(AttributeTargets.Constructor)] 15 | #if PolyPublic 16 | public 17 | #endif 18 | sealed class SetsRequiredMembersAttribute : 19 | Attribute; 20 | #else 21 | using System.Runtime.CompilerServices; 22 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute))] 23 | #endif -------------------------------------------------------------------------------- /src/Polyfill/SkipLocalsInitAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using System.Diagnostics; 9 | using System.Diagnostics.CodeAnalysis; 10 | 11 | using Targets = AttributeTargets; 12 | 13 | /// 14 | /// Used to indicate to the compiler that the .locals init 15 | /// flag should not be set in method headers. 16 | /// 17 | [ExcludeFromCodeCoverage] 18 | [DebuggerNonUserCode] 19 | [AttributeUsage( 20 | validOn: Targets.Module | 21 | Targets.Class | 22 | Targets.Struct | 23 | Targets.Interface | 24 | Targets.Constructor | 25 | Targets.Method | 26 | Targets.Property | 27 | Targets.Event, 28 | Inherited = false)] 29 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.skiplocalsinitattribute?view=net-10.0 30 | #if PolyPublic 31 | public 32 | #endif 33 | sealed class SkipLocalsInitAttribute : 34 | Attribute; 35 | #else 36 | using System.Runtime.CompilerServices; 37 | [assembly: TypeForwardedTo(typeof(SkipLocalsInitAttribute))] 38 | #endif -------------------------------------------------------------------------------- /src/Polyfill/StackTraceHiddenAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | namespace System.Diagnostics; 7 | 8 | using System.Diagnostics.CodeAnalysis; 9 | using Targets = AttributeTargets; 10 | 11 | /// 12 | /// Types and Methods attributed with StackTraceHidden will be omitted from the stack trace text shown in StackTrace.ToString() 13 | /// and Exception.StackTrace 14 | /// 15 | [ExcludeFromCodeCoverage] 16 | [DebuggerNonUserCode] 17 | [AttributeUsage( 18 | validOn: Targets.Class | 19 | Targets.Method | 20 | Targets.Constructor | 21 | Targets.Struct, 22 | Inherited = false)] 23 | #if PolyPublic 24 | public 25 | #endif 26 | sealed class StackTraceHiddenAttribute : 27 | Attribute; 28 | #else 29 | using System.Runtime.CompilerServices; 30 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.StackTraceHiddenAttribute))] 31 | #endif -------------------------------------------------------------------------------- /src/Polyfill/StringInterpolation/InterpolatedStringHandlerArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using Diagnostics; 9 | using Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// Indicates which arguments to a method involving an interpolated string handler should be passed to that handler. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage(AttributeTargets.Parameter)] 17 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.interpolatedstringhandlerargumentattribute?view=net-10.0 18 | #if PolyPublic 19 | public 20 | #endif 21 | sealed class InterpolatedStringHandlerArgumentAttribute : 22 | Attribute 23 | { 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// 27 | public InterpolatedStringHandlerArgumentAttribute(string argument) => Arguments = [argument]; 28 | 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) => Arguments = arguments; 33 | 34 | /// Gets the names of the arguments that should be passed to the handler. 35 | public string[] Arguments { get; } 36 | } 37 | 38 | #else 39 | using System.Runtime.CompilerServices; 40 | [assembly: TypeForwardedTo(typeof(InterpolatedStringHandlerArgumentAttribute))] 41 | #endif -------------------------------------------------------------------------------- /src/Polyfill/StringInterpolation/InterpolatedStringHandlerAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET6_0_OR_GREATER 5 | 6 | namespace System.Runtime.CompilerServices; 7 | 8 | using System.Diagnostics; 9 | using System.Diagnostics.CodeAnalysis; 10 | using Targets = AttributeTargets; 11 | 12 | /// 13 | /// Indicates the attributed type is to be used as an interpolated string handler. 14 | /// 15 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.interpolatedstringhandlerargumentattribute?view=net-10.0 16 | [ExcludeFromCodeCoverage] 17 | [DebuggerNonUserCode] 18 | [AttributeUsage( 19 | validOn: Targets.Class | 20 | Targets.Struct, 21 | Inherited = false)] 22 | #if PolyPublic 23 | public 24 | #endif 25 | sealed class InterpolatedStringHandlerAttribute : 26 | Attribute; 27 | 28 | #else 29 | using System.Runtime.CompilerServices; 30 | [assembly: TypeForwardedTo(typeof(InterpolatedStringHandlerAttribute))] 31 | #endif -------------------------------------------------------------------------------- /src/Polyfill/SuppressGCTransitionAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Runtime.InteropServices; 7 | 8 | using System.Diagnostics; 9 | using System.Diagnostics.CodeAnalysis; 10 | 11 | /// 12 | /// An attribute used to indicate a GC transition should be skipped when making an unmanaged function call. 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: AttributeTargets.Method, 18 | Inherited = false)] 19 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.suppressgctransitionattribute?view=net-10.0 20 | #if PolyPublic 21 | public 22 | #endif 23 | sealed class SuppressGCTransitionAttribute : 24 | Attribute; 25 | #else 26 | using System.Runtime.CompilerServices; 27 | [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.SuppressGCTransitionAttribute))] 28 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Trimming/DynamicallyAccessedMembersAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using Targets = AttributeTargets; 9 | 10 | /// 11 | /// Indicates that certain members on a specified are accessed dynamically, 12 | /// for example through . 13 | /// 14 | [ExcludeFromCodeCoverage] 15 | [DebuggerNonUserCode] 16 | [AttributeUsage( 17 | validOn: Targets.Class | 18 | Targets.Field | 19 | Targets.GenericParameter | 20 | Targets.Interface | 21 | Targets.Method | 22 | Targets.Parameter | 23 | Targets.Property | 24 | Targets.ReturnValue | 25 | Targets.Struct, 26 | Inherited = false)] 27 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.dynamicallyaccessedmembersattribute?view=net-10.0 28 | #if PolyPublic 29 | public 30 | #endif 31 | sealed class DynamicallyAccessedMembersAttribute : 32 | Attribute 33 | { 34 | /// 35 | /// Initializes a new instance of the class 36 | /// with the specified member types. 37 | /// 38 | public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) => 39 | MemberTypes = memberTypes; 40 | 41 | /// 42 | /// Gets the which specifies the type 43 | /// of members dynamically accessed. 44 | /// 45 | public DynamicallyAccessedMemberTypes MemberTypes { get; } 46 | } 47 | #else 48 | using System.Runtime.CompilerServices; 49 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute))] 50 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Trimming/RequiresDynamicCodeAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | #nullable enable 7 | 8 | namespace System.Diagnostics.CodeAnalysis; 9 | 10 | using Targets = AttributeTargets; 11 | 12 | /// 13 | /// Indicates that the specified method requires the ability to generate new code at runtime, 14 | /// for example through . 15 | /// 16 | [ExcludeFromCodeCoverage] 17 | [DebuggerNonUserCode] 18 | [AttributeUsage( 19 | validOn: Targets.Method | 20 | Targets.Constructor | 21 | Targets.Class, 22 | Inherited = false)] 23 | #if PolyPublic 24 | public 25 | #endif 26 | sealed class RequiresDynamicCodeAttribute : 27 | Attribute 28 | { 29 | /// 30 | /// Initializes a new instance of the class 31 | /// with the specified message. 32 | /// 33 | public RequiresDynamicCodeAttribute(string message) => 34 | Message = message; 35 | 36 | /// 37 | /// Gets a message that contains information about the usage of dynamic code. 38 | /// 39 | public string Message { get; } 40 | 41 | /// 42 | /// Gets or sets an optional URL that contains more information about the method, 43 | /// why it requires dynamic code, and what options a consumer has to deal with it. 44 | /// 45 | public string? Url { get; set; } 46 | } 47 | #else 48 | using System.Runtime.CompilerServices; 49 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute))] 50 | #endif -------------------------------------------------------------------------------- /src/Polyfill/Trimming/RequiresUnreferencedCodeAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | #nullable enable 7 | 8 | namespace System.Diagnostics.CodeAnalysis; 9 | 10 | using Targets = AttributeTargets; 11 | 12 | /// 13 | /// Indicates that the specified method requires dynamic access to code that is not referenced 14 | /// statically, for example through . 15 | /// 16 | [ExcludeFromCodeCoverage] 17 | [DebuggerNonUserCode] 18 | [AttributeUsage( 19 | validOn: Targets.Method | 20 | Targets.Constructor | 21 | Targets.Class, 22 | Inherited = false)] 23 | //Link: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.requiresunreferencedcodeattribute 24 | #if PolyPublic 25 | public 26 | #endif 27 | sealed class RequiresUnreferencedCodeAttribute : 28 | Attribute 29 | { 30 | /// 31 | /// Initializes a new instance of the class with the specified message. 32 | /// 33 | public RequiresUnreferencedCodeAttribute(string message) => 34 | Message = message; 35 | 36 | /// 37 | /// Gets a message that contains information about the usage of unreferenced code. 38 | /// 39 | public string Message { get; } 40 | 41 | /// 42 | /// Gets or sets an optional URL that contains more information about the method, 43 | /// why it requires unreferenced code, and what options a consumer has to deal with it. 44 | /// 45 | public string? Url { get; set; } 46 | } 47 | #else 48 | using System.Runtime.CompilerServices; 49 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute))] 50 | #endif -------------------------------------------------------------------------------- /src/Polyfill/UnmanagedCallersOnlyAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET 5 | 6 | #nullable enable 7 | 8 | namespace System.Runtime.InteropServices; 9 | 10 | using System.Diagnostics; 11 | using System.Diagnostics.CodeAnalysis; 12 | 13 | /// 14 | /// Any method marked with can be directly called from 15 | /// native code. The function token can be loaded to a local variable using the address-of operator 16 | /// in C# and passed as a callback to a native method. 17 | /// 18 | [ExcludeFromCodeCoverage] 19 | [DebuggerNonUserCode] 20 | [AttributeUsage( 21 | AttributeTargets.Method, 22 | Inherited = false)] 23 | #if PolyPublic 24 | public 25 | #endif 26 | sealed class UnmanagedCallersOnlyAttribute : 27 | Attribute 28 | { 29 | /// 30 | /// Optional. If omitted, the runtime will use the default platform calling convention. 31 | /// 32 | public Type[]? CallConvs; 33 | 34 | /// 35 | /// Optional. If omitted, no named export is emitted during compilation. 36 | /// 37 | public string? EntryPoint; 38 | } 39 | #else 40 | using System.Runtime.CompilerServices; 41 | [assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute))] 42 | #endif -------------------------------------------------------------------------------- /src/Polyfill/UnreachableException.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | #nullable enable 7 | 8 | namespace System.Diagnostics; 9 | 10 | using System; 11 | using System.Diagnostics.CodeAnalysis; 12 | 13 | /// 14 | /// Exception thrown when the program executes an instruction that was thought to be unreachable. 15 | /// 16 | /// 17 | /// 18 | [ExcludeFromCodeCoverage] 19 | [DebuggerNonUserCode] 20 | #if PolyPublic 21 | public 22 | #endif 23 | sealed class UnreachableException : Exception 24 | { 25 | /// 26 | /// Initializes a new instance of the class with the default error message. 27 | /// 28 | public UnreachableException() 29 | : base("The program executed an instruction that was thought to be unreachable.") 30 | { 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the 35 | /// class with a specified error message. 36 | /// 37 | public UnreachableException(string? message) 38 | : base(message) 39 | { 40 | } 41 | 42 | /// 43 | /// Initializes a new instance of the 44 | /// class with a specified error message and a reference to the inner exception that is the cause of 45 | /// this exception. 46 | /// 47 | public UnreachableException(string? message, Exception? innerException) 48 | : base(message, innerException) 49 | { 50 | } 51 | } 52 | #else 53 | using System.Runtime.CompilerServices; 54 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.UnreachableException))] 55 | #endif -------------------------------------------------------------------------------- /src/Polyfill/UnscopedRefAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | #pragma warning disable 3 | 4 | #if !NET7_0_OR_GREATER 5 | 6 | namespace System.Diagnostics.CodeAnalysis; 7 | 8 | using System.Diagnostics; 9 | 10 | using Targets = AttributeTargets; 11 | 12 | /// 13 | /// Used to indicate a byref escapes and is not scoped. 14 | /// 15 | [ExcludeFromCodeCoverage] 16 | [DebuggerNonUserCode] 17 | [AttributeUsage( 18 | validOn: Targets.Method | 19 | Targets.Property | 20 | Targets.Parameter, 21 | Inherited = false)] 22 | #if PolyPublic 23 | public 24 | #endif 25 | sealed class UnscopedRefAttribute : 26 | Attribute; 27 | #else 28 | using System.Runtime.CompilerServices; 29 | [assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.UnscopedRefAttribute))] 30 | #endif -------------------------------------------------------------------------------- /src/Polyfill/exclude.editorconfig: -------------------------------------------------------------------------------- 1 | # exclude code from dotnet format https://github.com/dotnet/sdk/issues/38906 2 | root = true -------------------------------------------------------------------------------- /src/PolyfillLib/PolyfillLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | true 5 | true 6 | net461;net462;net47;net471;net472;net48;net481;netstandard2.0;netstandard2.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/PolyfillUwp.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | ..\Shared.sln.DotSettings 3 | True 4 | True 5 | 1 6 | -------------------------------------------------------------------------------- /src/PublicTests/PublicTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | net462;net472;net48 5 | $(TargetFrameworks);netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/TargetFrameworkUsage/FakePolyfillsNamespace.cs: -------------------------------------------------------------------------------- 1 | namespace Polyfills; 2 | 3 | class FakePolyfillsNamespace; 4 | -------------------------------------------------------------------------------- /src/TargetFrameworkUsage/TargetFrameworkUsage.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | true 4 | net461 5 | $(TargetFrameworks);net5.0 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/TestIncludes.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Pollyfill\%(Filename).cs 5 | 6 | 7 | Pollyfill\Guard\%(RecursiveDir)%(Filename).cs 8 | 9 | 10 | Pollyfill\Nullable\%(RecursiveDir)%(Filename).cs 11 | 12 | 13 | Pollyfill\Nullability\%(RecursiveDir)%(Filename).cs 14 | 15 | 16 | Pollyfill\IndexRange\%(RecursiveDir)%(Filename).cs 17 | 18 | 19 | Pollyfill\StringInterpolation\%(RecursiveDir)%(Filename).cs 20 | 21 | 22 | Pollyfill\Trimming\%(RecursiveDir)%(Filename).cs 23 | 24 | 25 | Pollyfill\PlatformCompatibility\%(RecursiveDir)%(Filename).cs 26 | 27 | 28 | Pollyfill\Numbers\%(RecursiveDir)%(Filename).cs 29 | 30 | 31 | Pollyfill\Regex\%(RecursiveDir)%(Filename).cs 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/Tests/CallerArgumentExpressionUsage.cs: -------------------------------------------------------------------------------- 1 | #region CallerArgumentExpression 2 | 3 | static class FileUtil 4 | { 5 | public static void FileExists(string path, [CallerArgumentExpression("path")] string argumentName = "") 6 | { 7 | if (!File.Exists(path)) 8 | { 9 | throw new ArgumentException($"File not found. Path: {path}", argumentName); 10 | } 11 | } 12 | } 13 | 14 | static class FileUtilUsage 15 | { 16 | public static string[] Method(string path) 17 | { 18 | FileUtil.FileExists(path); 19 | return File.ReadAllLines(path); 20 | } 21 | } 22 | #endregion -------------------------------------------------------------------------------- /src/Tests/CollectionBuilderAttributeTests.cs: -------------------------------------------------------------------------------- 1 | [TestFixture] 2 | public class CollectionBuilderAttributeTests 3 | { 4 | [Test] 5 | public void CollectionBuilderAttributeTests_Compatibility_with_all_TargetFrameworks() 6 | { 7 | MyCollection myCollection = [1, 2, 3, 4, 5]; 8 | } 9 | 10 | [CollectionBuilder(typeof(MyCollection), nameof(Create))] 11 | public class MyCollection(ReadOnlySpan initValues) 12 | { 13 | readonly int[] values = initValues.ToArray(); 14 | public IEnumerator GetEnumerator() => ((IEnumerable)values).GetEnumerator(); 15 | 16 | public static MyCollection Create(ReadOnlySpan values) => new(values); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Tests/ConstantExpectedTests.cs: -------------------------------------------------------------------------------- 1 | [TestFixture] 2 | public class ConstantExpectedTests 3 | { 4 | public void Method([ConstantExpected] int b) { } 5 | public void MethodWithMinMax([ConstantExpected(Min = -5, Max = 10)] int b) { } 6 | 7 | // Invalid declaration 8 | // public void InvalidRange([ConstantExpected(Min = 5, Max = -5)] int b) { } 9 | 10 | public void Test(int variableNum) 11 | { 12 | // Valid calls 13 | const int constNum = 10; 14 | Method(constNum); 15 | MethodWithMinMax(constNum); 16 | Method(1); 17 | MethodWithMinMax(2); 18 | 19 | // Invalid calls 20 | 21 | // CA1857: The argument should be a constant for optimal performance 22 | // https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1857 23 | // Method(variableNum); 24 | 25 | // CA1857: The constant does not fit within the value bounds of '-5' to '10' 26 | // https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1857 27 | // MethodWithMinMax(15); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Tests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using NUnit.Framework; 2 | global using System; 3 | global using System.Diagnostics.CodeAnalysis; 4 | global using System.Text.RegularExpressions; 5 | -------------------------------------------------------------------------------- /src/Tests/IndexRangeSample.cs: -------------------------------------------------------------------------------- 1 | #region IndexRange 2 | 3 | [TestFixture] 4 | class IndexRangeSample 5 | { 6 | [Test] 7 | public void Range() 8 | { 9 | var substring = "value"[2..]; 10 | Assert.AreEqual("lue", substring); 11 | } 12 | 13 | [Test] 14 | public void Index() 15 | { 16 | var ch = "value"[^2]; 17 | Assert.AreEqual('u', ch); 18 | } 19 | 20 | [Test] 21 | public void ArrayIndex() 22 | { 23 | var array = new[] 24 | { 25 | "value1", 26 | "value2" 27 | }; 28 | 29 | var value = array[^2]; 30 | 31 | Assert.AreEqual("value1", value); 32 | } 33 | } 34 | 35 | #endregion 36 | 37 | //Array not supported due to no RuntimeHelpers.GetSubArray 38 | // [Test] 39 | // public void ArrayRange() 40 | // { 41 | // var array = new[] 42 | // { 43 | // "value1", 44 | // "value2" 45 | // }; 46 | // 47 | // var subArray = array[..1]; 48 | // 49 | // Assert.AreEqual(1, subArray.Length); 50 | // Assert.AreEqual("value1", subArray[0]); 51 | // } -------------------------------------------------------------------------------- /src/Tests/InitSample.cs: -------------------------------------------------------------------------------- 1 | #region IsExternalInit 2 | 3 | class InitSample 4 | { 5 | public int Member { get; init; } 6 | } 7 | 8 | #endregion -------------------------------------------------------------------------------- /src/Tests/ModuleInitSample.cs: -------------------------------------------------------------------------------- 1 | [TestFixture] 2 | public class ModuleInitSample 3 | { 4 | #region ModuleInitializerAttribute 5 | 6 | static bool InitCalled; 7 | 8 | [Test] 9 | public void ModuleInitTest() => 10 | Assert.True(InitCalled); 11 | 12 | [ModuleInitializer] 13 | public static void ModuleInit() => 14 | InitCalled = true; 15 | 16 | #endregion 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/Tests/NamedTupleSample.cs: -------------------------------------------------------------------------------- 1 | [TestFixture] 2 | public class NamedTupleSample 3 | { 4 | #region NamedTupleSample 5 | 6 | [Test] 7 | public void Usage() 8 | { 9 | var (value1, value2) = Method(); 10 | Trace.WriteLine(value1); 11 | Trace.WriteLine(value2); 12 | } 13 | 14 | static (string value1, bool value2) Method() => 15 | new("value", false); 16 | 17 | #endregion 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/Tests/Numbers/BytePolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class BytePolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(BytePolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(BytePolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(BytePolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(BytePolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(BytePolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(BytePolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(BytePolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/Numbers/DoublePolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class DoublePolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(DoublePolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(DoublePolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(DoublePolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(DoublePolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(DoublePolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(DoublePolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(DoublePolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/Numbers/IntPolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class IntPolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(IntPolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(IntPolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(IntPolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(IntPolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(IntPolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(IntPolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(IntPolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/Numbers/LongPolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class LongPolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(LongPolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(LongPolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(LongPolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(LongPolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(LongPolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(LongPolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(LongPolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/Numbers/SBytePolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class SBytePolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(SBytePolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(SBytePolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(SBytePolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(SBytePolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(SBytePolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(SBytePolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(SBytePolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/Numbers/ShortPolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class ShortPolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(ShortPolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(ShortPolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(ShortPolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(ShortPolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(ShortPolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(ShortPolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(ShortPolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/Numbers/UIntPolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class UIntPolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(UIntPolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(UIntPolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(UIntPolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(UIntPolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(UIntPolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(UIntPolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(UIntPolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/Numbers/ULongPolyfill.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class ULongPolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(ULongPolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(ULongPolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(ULongPolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(ULongPolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(ULongPolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(ULongPolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(ULongPolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/Numbers/UShortPolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | using System.Globalization; 4 | 5 | [TestFixture] 6 | partial class UShortPolyfillTest 7 | { 8 | [Test] 9 | public void TryParse() 10 | { 11 | Assert.True(UShortPolyfill.TryParse("1"u8, null, out var value)); 12 | Assert.AreEqual(1, value); 13 | 14 | Assert.True(UShortPolyfill.TryParse(['1'], out value)); 15 | Assert.AreEqual(1, value); 16 | 17 | Assert.True(UShortPolyfill.TryParse(['1'], null, out value)); 18 | Assert.AreEqual(1, value); 19 | 20 | Assert.True(UShortPolyfill.TryParse("1", null, out value)); 21 | Assert.AreEqual(1, value); 22 | 23 | Assert.True(UShortPolyfill.TryParse("1"u8, NumberStyles.Integer, null, out value)); 24 | Assert.AreEqual(1, value); 25 | 26 | Assert.True(UShortPolyfill.TryParse("1"u8, out value)); 27 | Assert.AreEqual(1, value); 28 | 29 | Assert.True(UShortPolyfill.TryParse(['1'], NumberStyles.Integer, null, out value)); 30 | Assert.AreEqual(1, value); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Tests/OverloadResolutionPriorityAttributeTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable UnusedParameter.Global 2 | #if FeatureMemory 3 | 4 | #region OverloadResolutionPriority 5 | 6 | [TestFixture] 7 | public class OverloadResolutionPriorityAttributeTests 8 | { 9 | [Test] 10 | public void Run() 11 | { 12 | int[] arr = [1, 2, 3]; 13 | //Prints "Span" because resolution priority is higher 14 | Method(arr); 15 | } 16 | 17 | [OverloadResolutionPriority(2)] 18 | static void Method(ReadOnlySpan list) => 19 | Console.WriteLine("Span"); 20 | 21 | [OverloadResolutionPriority(1)] 22 | static void Method(int[] list) => 23 | Console.WriteLine("Array"); 24 | } 25 | 26 | #endregion 27 | #endif -------------------------------------------------------------------------------- /src/Tests/PolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | [TestFixture] 4 | [DebuggerNonUserCode] 5 | partial class PolyfillTests; 6 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_ConcurrentBag.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void ConcurrentBagClear() 5 | { 6 | var bag = new ConcurrentBag 7 | { 8 | "Hello" 9 | }; 10 | bag.Clear(); 11 | Assert.AreEqual(0, bag.Count); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_ConcurrentDictionary.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void ConcurrentDictionaryGetOrAddFunc() 5 | { 6 | var dictionary = new ConcurrentDictionary(); 7 | 8 | Func valueFactory = static (key, arg) => arg.Length; 9 | 10 | var value = dictionary.GetOrAdd("Hello", valueFactory, "World"); 11 | 12 | Assert.AreEqual(5, value); 13 | 14 | value = dictionary.GetOrAdd("Hello", valueFactory, "Universe"); 15 | 16 | Assert.AreEqual(5, value); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_ConcurrentQueue.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void ConcurrentQueueClear() 5 | { 6 | var bag = new ConcurrentQueue(); 7 | bag.Enqueue("Hello"); 8 | bag.Clear(); 9 | Assert.AreEqual(0, bag.Count); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Delegate.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | public static event EventHandler? EventForHasSingleTarget; 4 | 5 | [Test] 6 | public void HasSingleTarget() 7 | { 8 | EventForHasSingleTarget += Handler; 9 | Assert.IsTrue(EventForHasSingleTarget.HasSingleTarget()); 10 | EventForHasSingleTarget += Handler; 11 | Assert.IsFalse(EventForHasSingleTarget.HasSingleTarget()); 12 | var action = () => 13 | { 14 | }; 15 | Assert.IsTrue(action.HasSingleTarget()); 16 | action += action; 17 | Assert.IsFalse(action.HasSingleTarget()); 18 | } 19 | 20 | static void Handler(object? sender, EventArgs e) 21 | { 22 | } 23 | 24 | public static event EventHandler? EventForEnumerateInvocationList; 25 | 26 | [Test] 27 | public void EnumerateInvocationList() 28 | { 29 | var count = 0; 30 | 31 | EventForEnumerateInvocationList += (_, _) => count++; 32 | 33 | foreach (var item in DelegatePolyfill.EnumerateInvocationList(EventForEnumerateInvocationList)) 34 | { 35 | item(this, EventArgs.Empty); 36 | } 37 | 38 | Assert.AreEqual(1, count); 39 | } 40 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Guid.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | static Regex guidV7Regex = new("^[0-9a-f]{8}(?:\\-[0-9a-f]{4}){3}-[0-9a-f]{12}$"); 4 | 5 | [Test] 6 | public void GuidCreate7() 7 | { 8 | var guid = GuidPolyfill.CreateVersion7(); 9 | Assert.IsTrue(guidV7Regex.IsMatch(guid.ToString())); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_HashSet.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void TryGetValue() 5 | { 6 | var value = "value"; 7 | var set = new HashSet 8 | { 9 | value 10 | }; 11 | var found = set.TryGetValue("value", out var result); 12 | Assert.True(found); 13 | Assert.AreSame(value, result!); 14 | found = set.TryGetValue("value2", out result); 15 | Assert.Null(result); 16 | Assert.False(found); 17 | } 18 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_IReadOnlyDictionary.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void IReadOnlyDictionaryGetValueOrDefault() 5 | { 6 | var dictionary = new Dictionary 7 | { 8 | {"key", "value"} 9 | }; 10 | 11 | Assert.AreEqual("value", dictionary.GetValueOrDefault("key")); 12 | Assert.AreEqual(null, dictionary.GetValueOrDefault("key1")); 13 | Assert.AreEqual("value1", dictionary.GetValueOrDefault("key1","value1")); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_List.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void IListAsReadOnly() 5 | { 6 | IList list = ['a']; 7 | var readOnly = list.AsReadOnly(); 8 | Assert.AreEqual('a', readOnly[0]); 9 | } 10 | 11 | [Test] 12 | public void ListAddRangeReadOnlySpan() 13 | { 14 | var list = new List(); 15 | list.AddRange("ab".AsSpan()); 16 | Assert.AreEqual('a', list[0]); 17 | Assert.AreEqual('b', list[1]); 18 | } 19 | 20 | [Test] 21 | public void ListInsertRangeReadOnlySpan() 22 | { 23 | var list = new List 24 | { 25 | 'a' 26 | }; 27 | list.InsertRange(1, "bc".AsSpan()); 28 | Assert.AreEqual('b', list[1]); 29 | Assert.AreEqual('c', list[2]); 30 | } 31 | 32 | [Test] 33 | public void ListCopyToSpan() 34 | { 35 | var list = new List 36 | { 37 | 'a' 38 | }; 39 | var array = new char[1]; 40 | list.CopyTo(array.AsSpan()); 41 | Assert.AreEqual('a', array[0]); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Memory_CountAny.cs: -------------------------------------------------------------------------------- 1 | #if FeatureMemory && NET8_0_OR_GREATER 2 | using System.Buffers; 3 | 4 | partial class PolyfillTests 5 | { 6 | [Test] 7 | public void ReadOnlySpan_CountAny() 8 | { 9 | ReadOnlySpan span = ['a', 'b', 'c']; 10 | var values = SearchValues.Create(['b', 'c']); 11 | Assert.AreEqual(2, span.CountAny(values)); 12 | Assert.AreEqual(2, span.CountAny('b', 'c')); 13 | Assert.AreEqual(2, span.CountAny(['b', 'c'], EqualityComparer.Default)); 14 | } 15 | } 16 | #endif -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Memory_IndexOf.cs: -------------------------------------------------------------------------------- 1 | #if FeatureMemory && NET8_0_OR_GREATER 2 | partial class PolyfillTests 3 | { 4 | [Test] 5 | public void ReadOnlySpan_IndexOf_FindsValue() 6 | { 7 | ReadOnlySpan span = [1, 2, 3, 4, 5]; 8 | var result = span.IndexOf(3, null); 9 | Assert.AreEqual(2, result); 10 | } 11 | 12 | [Test] 13 | public void ReadOnlySpan_IndexOf_ValueNotFound_ReturnsMinusOne() 14 | { 15 | ReadOnlySpan span = [1, 2, 3, 4, 5]; 16 | var result = span.IndexOf(6, null); 17 | Assert.AreEqual(-1, result); 18 | } 19 | 20 | [Test] 21 | public void ReadOnlySpan_IndexOf_EmptySpan_ReturnsMinusOne() 22 | { 23 | var span = ReadOnlySpan.Empty; 24 | var result = span.IndexOf(1, null); 25 | Assert.AreEqual(-1, result); 26 | } 27 | 28 | [Test] 29 | public void ReadOnlySpan_IndexOf_WithCustomComparer_FindsValue() 30 | { 31 | ReadOnlySpan span = new[] {"a", "b", "c"}; 32 | var result = span.IndexOf("B", StringComparer.OrdinalIgnoreCase); 33 | Assert.AreEqual(1, result); 34 | } 35 | 36 | [Test] 37 | public void ReadOnlySpan_IndexOf_WithCustomComparer_ValueNotFound_ReturnsMinusOne() 38 | { 39 | ReadOnlySpan span = new[] {"a", "b", "c"}; 40 | var result = span.IndexOf("d", StringComparer.OrdinalIgnoreCase); 41 | Assert.AreEqual(-1, result); 42 | } 43 | } 44 | #endif -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_MicroNanosecond.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | static DateTimeOffset dateTimeOffset = DateTimeOffset.Now; 4 | static DateTime dateTime = DateTime.Now; 5 | 6 | [Test] 7 | public void AddMicroseconds() 8 | { 9 | var fromTicksDateTimeOffset = dateTimeOffset.AddSeconds(1); 10 | var fromMicrosecondsDateTimeOffset = dateTimeOffset.AddMicroseconds(1000000); 11 | Assert.AreEqual(fromTicksDateTimeOffset, fromMicrosecondsDateTimeOffset); 12 | 13 | var fromTicksDateTime = dateTime.AddSeconds(1); 14 | var fromMicrosecondsDateTime = dateTime.AddMicroseconds(1000000); 15 | Assert.AreEqual(fromTicksDateTime, fromMicrosecondsDateTime); 16 | } 17 | 18 | #if NET7_0_OR_GREATER 19 | static TimeSpan timeSpan = DateTime.Now.TimeOfDay; 20 | [Test] 21 | public void Nanoseconds() 22 | { 23 | Assert.AreEqual(dateTimeOffset.Nanosecond, dateTimeOffset.Nanosecond()); 24 | Assert.AreEqual(timeSpan.Nanoseconds, timeSpan.Nanoseconds()); 25 | Assert.AreEqual(dateTime.Nanosecond, dateTime.Nanosecond()); 26 | } 27 | 28 | [Test] 29 | public void Microsecond() 30 | { 31 | Assert.AreEqual(dateTimeOffset.Microsecond, dateTimeOffset.Microsecond()); 32 | Assert.AreEqual(timeSpan.Microseconds, timeSpan.Microseconds()); 33 | Assert.AreEqual(dateTime.Microsecond, dateTime.Microsecond()); 34 | } 35 | #endif 36 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Normalization.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void GetNormalizedLength_ShouldReturnCorrectLength() 5 | { 6 | var span = "Café".AsSpan(); 7 | var normalizedLength = span.GetNormalizedLength(NormalizationForm.FormC); 8 | 9 | Assert.AreEqual(4, normalizedLength); 10 | } 11 | 12 | [Test] 13 | public void TryNormalize_ShouldNormalizeSuccessfully() 14 | { 15 | var source = "Café".AsSpan(); 16 | Span destination = new char[10]; 17 | var success = source.TryNormalize(destination, out var charsWritten, NormalizationForm.FormC); 18 | 19 | Assert.IsTrue(success); 20 | Assert.AreEqual(4, charsWritten); 21 | Assert.AreEqual("Café", destination.Slice(0, charsWritten).ToString()); 22 | } 23 | 24 | [Test] 25 | public void TryNormalize_ShouldFailWhenDestinationTooSmall() 26 | { 27 | var source = "Café".AsSpan(); 28 | Span destination = new char[2]; 29 | var success = source.TryNormalize(destination, out var charsWritten, NormalizationForm.FormC); 30 | 31 | Assert.IsFalse(success); 32 | Assert.AreEqual(0, charsWritten); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_OrderedDictionary.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | #if NET9_0_OR_GREATER 4 | [Test] 5 | public void OrderedDictionaryTryAdd() 6 | { 7 | var dictionary = new OrderedDictionary(); 8 | var key = "Hello"; 9 | var value = 5; 10 | var result = dictionary.TryAdd(key, value, out var index); 11 | Assert.IsTrue(result); 12 | Assert.AreEqual(0, index); 13 | } 14 | 15 | [Test] 16 | public void OrderedDictionaryTryGetValue() 17 | { 18 | var dictionary = new OrderedDictionary(); 19 | var key = "Hello"; 20 | var value = 5; 21 | dictionary.TryAdd(key, value, out _); 22 | var result = dictionary.TryGetValue(key, out var valueOut, out var index); 23 | Assert.IsTrue(result); 24 | Assert.AreEqual(value, valueOut); 25 | Assert.AreEqual(0, index); 26 | } 27 | #endif 28 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Process.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test, RequiresThread] 4 | [TestCase(0)] // poll 5 | [TestCase(10)] // real timeout 6 | public void Process_CurrentProcess_WaitAsyncNeverCompletes(int milliseconds) 7 | { 8 | using var cancelSource = new CancelSource(milliseconds); 9 | var cancel = cancelSource.Token; 10 | var process = Process.GetCurrentProcess(); 11 | 12 | var ex = Assert.CatchAsync(() => process.WaitForExitAsync(cancel)) as OperationCanceledException; 13 | 14 | Assert.IsNotNull(ex); 15 | Assert.AreEqual(cancel, ex!.CancellationToken); 16 | Assert.False(process.HasExited); 17 | } 18 | 19 | [Test, RequiresThread] 20 | public void Process_WaitForExitAsync_NotDirected_ThrowsInvalidOperationException() 21 | { 22 | var process = new Process(); 23 | Assert.ThrowsAsync(async () => await process.WaitForExitAsync()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Regex.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void RegexIsMatch() 5 | { 6 | var regex = new Regex(@"\d+"); 7 | var match = regex.Match("a55a"); 8 | Assert.IsTrue(match.Success); 9 | } 10 | 11 | [Test] 12 | public void EnumerateMatches() 13 | { 14 | var regex = new Regex(@"\d+"); 15 | var span = "a55a".AsSpan(); 16 | var found = false; 17 | foreach (var match in regex.EnumerateMatches(span)) 18 | { 19 | found = true; 20 | Assert.AreEqual(1, match.Index); 21 | Assert.AreEqual(2, match.Length); 22 | } 23 | 24 | Assert.IsTrue(found); 25 | } 26 | 27 | [Test] 28 | public void EnumerateMatchesStatic() 29 | { 30 | var span = "a55a".AsSpan(); 31 | var found = false; 32 | foreach (var match in RegexPolyfill.EnumerateMatches(span, @"\d+")) 33 | { 34 | found = true; 35 | Assert.AreEqual(1, match.Index); 36 | Assert.AreEqual(2, match.Length); 37 | } 38 | 39 | Assert.IsTrue(found); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_SortedList.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void SortedListGetKeyAtIndex() 5 | { 6 | var list = new SortedList 7 | { 8 | { 9 | 3, 'x' 10 | } 11 | }; 12 | var key = list.GetKeyAtIndex(0); 13 | Assert.AreEqual(3, key); 14 | } 15 | 16 | [Test] 17 | public void SortedListGetValueAtIndex() 18 | { 19 | var list = new SortedList 20 | { 21 | { 22 | 3, 'x' 23 | } 24 | }; 25 | var value = list.GetValueAtIndex(0); 26 | Assert.AreEqual('x', value); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Stack.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void Stack_TryPeek() 5 | { 6 | var stack = new Stack(); 7 | 8 | // Test when stack is empty 9 | var result = stack.TryPeek(out var value); 10 | Assert.IsFalse(result); 11 | Assert.AreEqual(0, value); 12 | 13 | // Test when stack has elements 14 | stack.Push(1); 15 | stack.Push(2); 16 | stack.Push(3); 17 | 18 | result = stack.TryPeek(out value); 19 | Assert.IsTrue(result); 20 | // The top element should be 3 21 | Assert.AreEqual(3, value); 22 | 23 | // Ensure the stack is not modified 24 | Assert.AreEqual(3, stack.Count); 25 | } 26 | 27 | [Test] 28 | public void Stack_TryPop() 29 | { 30 | var stack = new Stack(); 31 | 32 | // Test when stack is empty 33 | var result = stack.TryPop(out var value); 34 | Assert.IsFalse(result); 35 | Assert.AreEqual(0, value); 36 | 37 | // Test when stack has elements 38 | stack.Push(1); 39 | stack.Push(2); 40 | stack.Push(3); 41 | 42 | result = stack.TryPop(out value); 43 | Assert.IsTrue(result); 44 | // The top element should be 3 45 | Assert.AreEqual(3, value); 46 | 47 | // Ensure the stack is modified 48 | Assert.AreEqual(2, stack.Count); 49 | Assert.AreEqual(2, stack.Peek()); 50 | } 51 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Stream.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public async Task StreamReadAsyncMemory() 5 | { 6 | var input = new byte[]{1,2}; 7 | using var stream = new MemoryStream(input); 8 | var result = new byte[2]; 9 | var memory = new Memory(result); 10 | var read = await stream.ReadAsync(memory); 11 | Assert.AreEqual(2, read); 12 | Assert.IsTrue(input.SequenceEqual(result)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_StreamReader.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public async Task StreamReaderReadAsync() 5 | { 6 | using var stream = new MemoryStream("value"u8.ToArray()); 7 | var result = new char[5]; 8 | var memory = new Memory(result); 9 | using var reader = new StreamReader(stream); 10 | var read = await reader.ReadAsync(memory); 11 | Assert.AreEqual(5, read); 12 | Assert.IsTrue("value".SequenceEqual(result)); 13 | } 14 | 15 | [Test] 16 | public async Task StreamReaderReadToEndAsync() 17 | { 18 | using var stream = new MemoryStream("value"u8.ToArray()); 19 | using var reader = new StreamReader(stream); 20 | var read = await reader.ReadToEndAsync(Cancel.None); 21 | Assert.AreEqual("value", read); 22 | } 23 | 24 | [Test] 25 | public async Task StreamReaderReadLineAsync() 26 | { 27 | using var stream = new MemoryStream("line1\nline2"u8.ToArray()); 28 | using var reader = new StreamReader(stream); 29 | var read = await reader.ReadLineAsync(CancellationToken.None); 30 | Assert.AreEqual("line1", read); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_String.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | partial class PolyfillTests 4 | { 5 | [Test] 6 | public void GetHashCodeStringComparison() 7 | { 8 | var hash = "value".GetHashCode(StringComparison.Ordinal); 9 | Assert.AreNotEqual(0, hash); 10 | } 11 | 12 | [Test] 13 | public void EndsWith() 14 | { 15 | Assert.True("value".EndsWith('e')); 16 | Assert.True("e".EndsWith('e')); 17 | Assert.False("".EndsWith('e')); 18 | } 19 | 20 | [Test] 21 | [Platform("Win")] 22 | public void ReplaceLineEndings() 23 | { 24 | Assert.AreEqual("a\r\nb\r\nc\r\nd", "a\rb\nc\r\nd".ReplaceLineEndings()); 25 | Assert.AreEqual("a_b_c_d", "a\rb\nc\r\nd".ReplaceLineEndings("_")); 26 | } 27 | 28 | [Test] 29 | public void CopyTo() 30 | { 31 | var span = new Span(new char[1]); 32 | "a".CopyTo(span); 33 | Assert.AreEqual("a", span.ToString()); 34 | } 35 | 36 | [Test] 37 | public void TryCopyTo() 38 | { 39 | var span = new Span(new char[1]); 40 | Assert.IsTrue("a".TryCopyTo(span)); 41 | Assert.AreEqual("a", span.ToString()); 42 | } 43 | 44 | [Test] 45 | public void StringContainsStringComparison() => 46 | Assert.True("value".Contains("E", StringComparison.OrdinalIgnoreCase)); 47 | 48 | [Test] 49 | public void StartsWith() 50 | { 51 | Assert.True("value".StartsWith('v')); 52 | Assert.True("v".StartsWith('v')); 53 | Assert.False("".StartsWith('v')); 54 | } 55 | 56 | [Test] 57 | public void Split() 58 | { 59 | Assert.AreEqual(new []{"a","b"}, "a b".Split(' ', StringSplitOptions.RemoveEmptyEntries)); 60 | Assert.AreEqual(new []{"a","b"}, "a b".Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)); 61 | } 62 | 63 | [Test] 64 | public void ContainsChar() => 65 | Assert.True("value".Contains('v')); 66 | } 67 | -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_TaskCompletionSource.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable CS4014 2 | partial class PolyfillTests 3 | { 4 | [Test] 5 | public async Task TaskCompletionSource() 6 | { 7 | var completionSource = new TaskCompletionSource(); 8 | 9 | // Simulate some background work 10 | Task.Run(async () => 11 | { 12 | await Task.Delay(10); // Simulate a delay 13 | completionSource.SetResult(); 14 | }); 15 | 16 | // Await the task 17 | await completionSource.Task; 18 | Console.WriteLine("Task completed successfully"); 19 | } 20 | 21 | [Test] 22 | public async Task TaskCompletionSource_SetCanceled_WithCancellationToken() 23 | { 24 | var completionSource = new TaskCompletionSource(); 25 | var tokenSource = new CancellationTokenSource(); 26 | 27 | // Simulate some background work that will cancel the task 28 | Task.Run(async () => 29 | { 30 | await Task.Delay(20); // Simulate a delay 31 | completionSource.SetCanceled(tokenSource.Token); 32 | }); 33 | 34 | try 35 | { 36 | // Await the task 37 | var result = await completionSource.Task; 38 | Console.WriteLine($"Task completed with result: {result}"); 39 | } 40 | catch (TaskCanceledException) 41 | { 42 | Console.WriteLine("Task was canceled."); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_Type.cs: -------------------------------------------------------------------------------- 1 | partial class PolyfillTests 2 | { 3 | [Test] 4 | public void IsAssignableTo() 5 | { 6 | Assert.True(typeof(List).IsAssignableTo(typeof(IList))); 7 | Assert.True(typeof(List).IsAssignableTo()); 8 | Assert.False(typeof(List).IsAssignableTo(typeof(string))); 9 | Assert.False(typeof(List).IsAssignableTo()); 10 | Assert.False(typeof(List).IsAssignableTo(null)); 11 | } 12 | 13 | [Test] 14 | public void IsAssignableFrom() 15 | { 16 | Assert.True(typeof(IList).IsAssignableFrom>()); 17 | Assert.False(typeof(string).IsAssignableFrom>()); 18 | } 19 | 20 | public class WithGenericMethod 21 | { 22 | public void Method(string value) 23 | { 24 | } 25 | public void Method() 26 | { 27 | } 28 | public void Method(string value) 29 | { 30 | } 31 | public void Method(string value1, string value2) 32 | { 33 | } 34 | } 35 | 36 | #if !NETFRAMEWORK && !NETSTANDARD2_0 && !NETCOREAPP2_0 37 | [Test] 38 | public void Type_GetMethod() 39 | { 40 | var type = typeof(WithGenericMethod); 41 | var method = type.GetMethod("Method", 1, BindingFlags.Public | BindingFlags.Instance, [typeof(string)])!; 42 | Assert.AreEqual("Method", method.Name); 43 | Assert.AreEqual(1, method.GetParameters().Length); 44 | Assert.AreEqual(1, method.GetGenericArguments().Length); 45 | } 46 | #endif 47 | } -------------------------------------------------------------------------------- /src/Tests/PolyfillTests_XDocument.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using System.Xml.Linq; 3 | 4 | partial class PolyfillTests 5 | { 6 | [Test] 7 | public async Task XDocumentSaveAsyncXmlWriter() 8 | { 9 | var document = GetXDocument(); 10 | var builder = new StringBuilder(); 11 | var settings = new XmlWriterSettings 12 | { 13 | OmitXmlDeclaration = true, 14 | Indent = true, 15 | Async = true 16 | }; 17 | 18 | using var writer = XmlWriter.Create(builder, settings); 19 | await document.SaveAsync(writer, Cancel.None); 20 | await writer.FlushAsync(); 21 | Assert.AreEqual("", builder.ToString()); 22 | } 23 | 24 | [Test] 25 | public async Task XDocumentSaveAsyncStream() 26 | { 27 | var document = GetXDocument(); 28 | using var stream = new MemoryStream(); 29 | 30 | await document.SaveAsync(stream, SaveOptions.DisableFormatting, Cancel.None); 31 | stream.Position = 0; 32 | using var reader = new StreamReader(stream); 33 | var result = await reader.ReadToEndAsync(); 34 | 35 | Assert.AreEqual("", result); 36 | } 37 | 38 | static XDocument GetXDocument() => 39 | new(new XElement("Child")); 40 | } -------------------------------------------------------------------------------- /src/Tests/RandomPolyfillTests.cs: -------------------------------------------------------------------------------- 1 | [TestFixture] 2 | public class RandomPolyfillTests 3 | { 4 | [Test, Repeat(100)] 5 | public void NextInt() 6 | { 7 | var number = RandomPolyfill.Shared.Next(10); 8 | 9 | Assert.That(number, Is.InRange(0, 10)); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Tests/RangeIndexUsage.cs: -------------------------------------------------------------------------------- 1 | 2 | // ReSharper disable UnusedVariable 3 | #region RangeIndex 4 | 5 | public class RangeIndexUsage 6 | { 7 | public RangeIndexUsage() 8 | { 9 | var subString = "value"[1..]; 10 | } 11 | } 12 | 13 | #endregion -------------------------------------------------------------------------------- /src/Tests/SetsRequiredMembersUsage.cs: -------------------------------------------------------------------------------- 1 | class SetsRequiredMembersUsage 2 | { 3 | #region Required 4 | 5 | public class Person 6 | { 7 | public Person() 8 | { 9 | } 10 | 11 | [SetsRequiredMembers] 12 | public Person(string name) => 13 | Name = name; 14 | 15 | public required string Name { get; init; } 16 | } 17 | 18 | #endregion 19 | } -------------------------------------------------------------------------------- /src/Tests/SolutionDirectoryFinder.cs: -------------------------------------------------------------------------------- 1 | static class SolutionDirectoryFinder 2 | { 3 | public static string Find([CallerFilePath] string sourceFile = "") 4 | { 5 | if (TryFind(sourceFile, out var solutionDirectory)) 6 | { 7 | return solutionDirectory; 8 | } 9 | 10 | throw new("Could not find solution directory"); 11 | } 12 | 13 | public static bool TryFind(string sourceFile, [NotNullWhen(true)] out string? path) 14 | { 15 | var currentDirectory = Directory.GetParent(sourceFile)!.FullName; 16 | do 17 | { 18 | if (Directory.GetFiles(currentDirectory, "*.sln").Length > 0) 19 | { 20 | path = currentDirectory; 21 | return true; 22 | } 23 | 24 | var parent = Directory.GetParent(currentDirectory); 25 | if (parent == null) 26 | { 27 | path = null; 28 | return false; 29 | } 30 | 31 | currentDirectory = parent.FullName; 32 | } while (true); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Tests/StringInterpolationTests.cs: -------------------------------------------------------------------------------- 1 | #if FeatureMemory 2 | 3 | [TestFixture] 4 | public class StringInterpolationTests 5 | { 6 | [Test] 7 | public void ShouldInterpolateString() 8 | { 9 | Span buffer = ['H', 'e', 'l', 'l', 'o']; 10 | var number = 15; 11 | var result = $"{buffer}, you're {number} years old"; 12 | 13 | Assert.AreEqual("Hello, you're 15 years old", result); 14 | } 15 | 16 | [Test] 17 | public void ShouldInterpolateStringBuilder() 18 | { 19 | var builder = new StringBuilder(); 20 | Span buffer = ['H', 'e', 'l', 'l', 'o']; 21 | var number = 15; 22 | Polyfill.Append(builder, $"{buffer}, you're {number} years old {builder.ToString()}"); 23 | var result = builder.ToString(); 24 | 25 | Assert.AreEqual("Hello, you're 15 years old Hello, you're 15 years old ", result); 26 | } 27 | } 28 | #endif -------------------------------------------------------------------------------- /src/Tests/StringPolyfillTests.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable PartialTypeWithSinglePart 2 | 3 | [TestFixture] 4 | partial class StringPolyfillTest 5 | { 6 | [Test] 7 | public void Join() 8 | { 9 | Assert.AreEqual("bac", StringPolyfill.Join('a', ["b","c"])); 10 | Assert.AreEqual("ba1c", StringPolyfill.Join("a1", ["b","c"])); 11 | Assert.AreEqual("bac", StringPolyfill.Join('a', new object[]{"b","c"})); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | net462;net472;net48;net6.0-windows 5 | $(TargetFrameworks);netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Tests/UnreachableExceptionTests.cs: -------------------------------------------------------------------------------- 1 | [TestFixture] 2 | public class UnreachableExceptionTests 3 | { 4 | [Test] 5 | public void UnreachableException_Compatibility_with_all_TargetFrameworks() => 6 | _ = Assert.Throws(() => throw new UnreachableException()); 7 | } 8 | -------------------------------------------------------------------------------- /src/UnsafeTests/SkipLocalsInitExample.cs: -------------------------------------------------------------------------------- 1 | #region SkipLocalsInit 2 | 3 | class SkipLocalsInitSample 4 | { 5 | [SkipLocalsInit] 6 | static void ReadUninitializedMemory() 7 | { 8 | Span numbers = stackalloc int[120]; 9 | for (var i = 0; i < 120; i++) 10 | { 11 | Console.WriteLine(numbers[i]); 12 | } 13 | } 14 | } 15 | 16 | #endregion -------------------------------------------------------------------------------- /src/UnsafeTests/UnsafeTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(NoWarn);PolyfillTargetsForNuget 4 | net462;net472;net48 5 | $(TargetFrameworks);netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0 6 | True 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/appveyor.yml: -------------------------------------------------------------------------------- 1 | image: 2 | - Visual Studio 2022 3 | - macOS 4 | #- Ubuntu 5 | environment: 6 | DOTNET_NOLOGO: true 7 | DOTNET_CLI_TELEMETRY_OPTOUT: true 8 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 9 | build_script: 10 | - pwsh: | 11 | if ($isWindows) { 12 | Invoke-WebRequest "https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.ps1" -OutFile "./dotnet-install.ps1" 13 | ./dotnet-install.ps1 -JSonFile src/global.json -Architecture x64 -InstallDir 'C:\Program Files\dotnet' 14 | ./dotnet-install.ps1 -Version 5.0.408 -Architecture x64 -InstallDir 'C:\Program Files\dotnet' 15 | ./dotnet-install.ps1 -Version 9.0.203 -Architecture x64 -InstallDir 'C:\Program Files\dotnet' 16 | dotnet build src/Polyfill.sln --configuration Release --verbosity quiet 17 | dotnet test src/Polyfill.sln --configuration Release --no-build --no-restore 18 | msbuild.exe src/PolyfillUwp.sln /p:Configuration=Release -verbosity:quiet 19 | } 20 | else { 21 | Invoke-WebRequest "https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.sh" -OutFile "./dotnet-install.sh" 22 | sudo chmod u+x dotnet-install.sh 23 | if ($isMacOS) { 24 | sudo ./dotnet-install.sh --jsonfile src/global.json --architecture x64 --install-dir '/usr/local/share/dotnet' 25 | sudo ./dotnet-install.sh --version 5.0.408 --architecture x64 --install-dir '/usr/local/share/dotnet' 26 | sudo ./dotnet-install.sh --version 9.0.203 --architecture x64 --install-dir '/usr/local/share/dotnet' 27 | } else { 28 | sudo ./dotnet-install.sh --jsonfile src/global.json --architecture x64 --install-dir '/usr/share/dotnet' 29 | } 30 | dotnet build src/Polyfill.sln --configuration Release --verbosity quiet 31 | dotnet test src/Polyfill.sln --configuration Release --no-build --no-restore 32 | } 33 | 34 | on_failure: 35 | - ps: Get-ChildItem *.received.* -recurse | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } 36 | test: off 37 | artifacts: 38 | - path: nugets\*.nupkg -------------------------------------------------------------------------------- /src/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "10.0.100-preview.6.25302.104", 4 | "allowPrerelease": true, 5 | "rollForward": "latestFeature" 6 | }, 7 | "msbuild-sdks": { 8 | "MSBuild.Sdk.Extras": "3.0.44" 9 | } 10 | } -------------------------------------------------------------------------------- /src/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonCropp/Polyfill/c7653d6b0f4592e732bc62c201fc7354d7e6b0ac/src/icon.png -------------------------------------------------------------------------------- /src/key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonCropp/Polyfill/c7653d6b0f4592e732bc62c201fc7354d7e6b0ac/src/key.snk -------------------------------------------------------------------------------- /src/mdsnippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/SimonCropp/MarkdownSnippets/master/schema.json", 3 | "MaxWidth": 300, 4 | "Convention": "InPlaceOverwrite" 5 | } -------------------------------------------------------------------------------- /src/nuget.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | --------------------------------------------------------------------------------