{"id":15631705,"url":"https://github.com/manuelroemer/nullable","last_synced_at":"2025-04-12T19:48:03.067Z","repository":{"id":35133105,"uuid":"210887776","full_name":"manuelroemer/Nullable","owner":"manuelroemer","description":"A source code only package which allows you to use .NET's nullable attributes in older target frameworks like .NET Standard 2.0 or the \"old\" .NET Framework.","archived":false,"fork":false,"pushed_at":"2024-02-14T10:10:06.000Z","size":107,"stargazers_count":188,"open_issues_count":1,"forks_count":8,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-04-12T19:47:49.759Z","etag":null,"topics":["allownull","attribute","compiletime","csharp","disallownull","doesnotreturn","doesnotreturnif","maybenull","maybenullwhen","membernotenull","membernotnullwhen","notnull","notnullifnotnull","notnullwhen","null","nullable","polyfill","source"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/Nullable","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/manuelroemer.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-25T16:10:40.000Z","updated_at":"2025-02-14T13:16:40.000Z","dependencies_parsed_at":"2024-01-06T14:56:58.391Z","dependency_job_id":"93e3ef40-616e-466e-abc8-182790bcfd35","html_url":"https://github.com/manuelroemer/Nullable","commit_stats":{"total_commits":59,"total_committers":6,"mean_commits":9.833333333333334,"dds":"0.10169491525423724","last_synced_commit":"efc65bbc068120e87aa08fb717c368e50973b56b"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manuelroemer%2FNullable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manuelroemer%2FNullable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manuelroemer%2FNullable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manuelroemer%2FNullable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/manuelroemer","download_url":"https://codeload.github.com/manuelroemer/Nullable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248625497,"owners_count":21135513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["allownull","attribute","compiletime","csharp","disallownull","doesnotreturn","doesnotreturnif","maybenull","maybenullwhen","membernotenull","membernotnullwhen","notnull","notnullifnotnull","notnullwhen","null","nullable","polyfill","source"],"created_at":"2024-10-03T10:41:17.961Z","updated_at":"2025-04-12T19:48:03.043Z","avatar_url":"https://github.com/manuelroemer.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nullable [![Nuget](https://img.shields.io/nuget/v/Nullable)](https://www.nuget.org/packages/Nullable)\n\n_Use .NET Core 3.0's new nullable attributes in older target frameworks._\n\n[:running: Quickstart](#quickstart) \u0026nbsp; | \u0026nbsp; [:books: Guides](https://github.com/manuelroemer/Nullable/wiki) \u0026nbsp; | \u0026nbsp; [:package: NuGet](https://www.nuget.org/packages/nullable)\n\n\u003chr/\u003e\n\n_You may also want to check out my [IsExternalInit](https://github.com/manuelroemer/IsExternalInit)\nproject which provides support for C# 9's `init` and `record` keywords for older target frameworks._\n\n\u003chr/\u003e\n\n\nWith the release of C# 8.0, support for [nullable reference types](https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/nullable-reference-types)\nhas been added to the language.\nFuthermore, .NET Core 3.0 added [new nullable attributes](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis?view=netcore-3.0)\nlike the [`AllowNullAttribute`](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.allownullattribute?view=netcore-3.0)\nwhich are sometimes required to exactly declare when and how `null` is allowed in specific code\nsections.\n\nUnfortunately, these attributes are not available in older target frameworks like .NET Standard 2.0\nwhich makes annotating existing code harder.\nLuckily, this problem can be solved by re-declaring the attributes as `internal class`es - the C#\ncompiler will still use them for generating warnings, even though the target framework doesn't\nsupport these attributes by itself.\n\nThis repository hosts the code for the [\"Nullable\" NuGet Package](https://www.nuget.org/packages/Nullable)\nwhich, when referenced, adds support for these attributes.\n\nThe code for these attributes is added **at compile time** and gets **built into the referencing project**.\nThis means that the resulting project **does not have an explicit dependency** on the `Nullable`\npackage, because the attributes are not distributed as a library.\n\nFuthermore, the code only gets added to the project if the nullable attributes are not already\nsupported by the target framework.\nThe images below show an example - in the library which targets .NET Standard 2.0, the attributes\nhave been added during the compilation.\nThat is not the case for the library targeting .NET Standard 2.1, because the attributes are\navailable through the .NET BCL there.\nThis allows you to easily **multi-target** your projects without having to change a single line of\ncode.\n\n| .NET Standard 2.0 | .NET Standard 2.1 |\n| ----------------- | ----------------- |\n| ![.NET Standard 2.0](.github/CompiledNetStandard2.0.png) | ![.NET Standard 2.1](.github/CompiledNetStandard2.1.png) |\n\n\n## Compatibility\n\nNullabe is currently compatible with the following target frameworks:\n\n* .NET Standard \u003e= 1.0\n* .NET Framework \u003e= 2.0\n\nPlease have a look at the [guides](https://github.com/manuelroemer/Nullable/wiki) for additional information on how to\ninstall the package for your target framework.\n\n\n## Quickstart\n\n\u003e :warning: **Important:** \u003cbr/\u003e\n\u003e You **must** use a C# version \u003e= 8.0 with the `Nullable` package - otherwise, your project won't compile.\n\nThe steps below assume that you are using the **new SDK `.csproj`** style.\nPlease find installation guides and notes for other project types (for example `packages.config`)\n[here](https://github.com/manuelroemer/Nullable/wiki).\n\n1. **Reference the package** \u003cbr/\u003e\n   Add the package to your project, for example via:\n\n   ```sh\n   Install-Package Nullable\n\n   --or--\n\n   dotnet add package Nullable\n   ```\n2. **Ensure that the package has been added as a development dependency** \u003cbr/\u003e\n   Open your `.csproj` file and ensure that the new package reference looks similar to this:\n\n   ```xml\n   \u003cPackageReference Include=\"Nullable\" Version=\"\u003cYOUR_VERSION\u003e\"\u003e\n     \u003cPrivateAssets\u003eall\u003c/PrivateAssets\u003e\n     \u003cIncludeAssets\u003eruntime; build; native; contentfiles; analyzers; buildtransitive\u003c/IncludeAssets\u003e\n   \u003c/PackageReference\u003e\n\n   \u003c!-- This style also works, but is not automatically used by .NET: --\u003e\n   \u003cPackageReference Include=\"Nullable\" Version=\"\u003cYOUR_VERSION\u003e\" PrivateAssets=\"all\" /\u003e\n   ```\n\n   This is especially important for libraries that are published to NuGet, because without this,\n   the library will have an **explicit dependency** on the `Nullable` package.\n3. **Build the project** \u003cbr/\u003e\n   Ensure that the project compiles. If a build error occurs, you will most likely have to update\n   the C# language version (see next step).\n4. **Enable Nullable Reference Types** \u003cbr/\u003e\n   Still in your `.csproj` file you need to activate the feature to fully use it.\n   The following activation sample is what seems to be the most common use case.\n   But do not hesitate to look at my [guides](https://github.com/manuelroemer/Nullable/wiki) for other considerations.\n\n   ```xml\n   \u003cPropertyGroup\u003e\n     \u003c!-- Your desired target frameworks. --\u003e\n     \u003cTargetFrameworks\u003enet472;netstandard2.0;netstandard2.1;netcoreapp3.0\u003c/TargetFrameworks\u003e\n     \n     \u003c!-- The C# language version to use. Must be at least 8.0 (other suggestions: 9.0, latest, preview).--\u003e\n     \u003cLangVersion\u003e8.0\u003c/LangVersion\u003e \u003c!-- or --\u003e \u003cLangVersion\u003elatest\u003c/LangVersion\u003e\n       \n     \u003c!-- Enable nullable reference types. You can also use \"annotations\" instead of \"enable\"\n          to prevent the compiler from emitting warnings. --\u003e\n     \u003cNullable\u003eenable\u003c/Nullable\u003e\n   \u003c/PropertyGroup\u003e\n   ```\n5. **For WPF users:** \u003cbr/\u003e\n   There [have been issues](https://github.com/manuelroemer/Nullable/issues/11) with WPF projects in the past\n   which resulted in compilation errors, however these have been fixed with the .NET 5.0.102 SDK.\n   To get Nullable working with your WPF project, ensure that you are using an SDK \u003e= 5.0.102 SDK and then\n   add the following configuration to your `.csproj` file:\n   \n   ```xml\n   \u003cUseWPF\u003etrue\u003c/UseWPF\u003e\n   \u003cIncludePackageReferencesDuringMarkupCompilation\u003etrue\u003c/IncludePackageReferencesDuringMarkupCompilation\u003e\n   ```\n\nYou should now be ready to use Nullable Reference Types and the corresponding attributes even when targeting legacy frameworks.\n\n\n## Compiler Constants\n\nThe [included C# file](https://github.com/manuelroemer/Nullable/blob/master/src/Nullable.ExcludeFromCodeCoverage/NullableAttributes.cs)\nmakes use of some compiler constants that can be used to enable or disable certain features.\n\n### `NULLABLE_ATTRIBUTES_DISABLE`\n\nIf the `NULLABLE_ATTRIBUTES_DISABLE` constant is defined, the attributes are excluded from the build.\nThis can be used to conditionally exclude the attributes from the build if they are not required.\n\nIn most cases, this should not be required, because the package automatically excludes the attributes\nfrom target frameworks that already support these attributes.\n\n\n### `NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE`\n\nBecause the attributes are added as source code, they could appear in code coverage reports.\nBy default, this is disabled via the [`ExcludeFromCodeCoverage`](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.excludefromcodecoverageattribute?view=netcore-3.0)\nand [`DebuggerNonUserCode`](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debuggernonusercodeattribute?view=netcore-3.0)\nattributes.\n\nBy defining the `NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE` constant, the [`ExcludeFromCodeCoverage`](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.excludefromcodecoverageattribute?view=netcore-3.0)\nand [`DebuggerNonUserCode`](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debuggernonusercodeattribute?view=netcore-3.0)\nattributes are not applied and the nullable attributes may therefore appear in code coverage reports.\n\n\n## Building\n\nBecause the package consists of source files, building works differently than a normal .NET project.\nIn essence, no build has to be made at all. Instead, the `*.cs` files are packaged into a NuGet package via a `.nuspec` file.\n\nThe solution contains a `_build` project which automatically performs these tasks though. You can then\nfind the resulting NuGet package file in the `artifacts` folder.\n\n\n## Contributing\n\nI don't expect this package to require many changes, but if something is not working for you or\nif you think that the source file should change, feel free to create an issue or Pull Request.\nI will be happy to discuss and potentially integrate your ideas!\n\n\n## License\n\nSee the [LICENSE](./LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanuelroemer%2Fnullable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanuelroemer%2Fnullable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanuelroemer%2Fnullable/lists"}