{"id":25621718,"url":"https://github.com/thecodetraveler/icommandattribute_nullableparameter_repro","last_synced_at":"2026-06-17T06:31:24.664Z","repository":{"id":68231099,"uuid":"497422285","full_name":"TheCodeTraveler/ICommandAttribute_NullableParameter_Repro","owner":"TheCodeTraveler","description":"A reproduction sample for CommunityToolkit.Command","archived":false,"fork":false,"pushed_at":"2022-05-28T21:12:07.000Z","size":20,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-14T05:31:21.726Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TheCodeTraveler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2022-05-28T20:34:07.000Z","updated_at":"2024-09-18T11:14:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"9ab32b8f-32ff-4b1d-aeee-16ebc24f317e","html_url":"https://github.com/TheCodeTraveler/ICommandAttribute_NullableParameter_Repro","commit_stats":null,"previous_names":["thecodetraveler/icommandattribute_nullableparameter_repro"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheCodeTraveler%2FICommandAttribute_NullableParameter_Repro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheCodeTraveler%2FICommandAttribute_NullableParameter_Repro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheCodeTraveler%2FICommandAttribute_NullableParameter_Repro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheCodeTraveler%2FICommandAttribute_NullableParameter_Repro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TheCodeTraveler","download_url":"https://codeload.github.com/TheCodeTraveler/ICommandAttribute_NullableParameter_Repro/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240155323,"owners_count":19756627,"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":[],"created_at":"2025-02-22T09:44:13.339Z","updated_at":"2026-05-28T00:30:15.698Z","avatar_url":"https://github.com/TheCodeTraveler.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ICommandAttribute_NullableParameter_Repro\n\nIn CommunityToolkit.Mvvm, when a tuple containing nullable reference types is used as a parameter for a method containing the attribute `[ICommand]`, the created `IAsyncRelayCommand` removes the nullability from each object.\n\n```cs\n[ICommand]\nvoid M1((string? text, bool isBusy) parameter)\n{\n}\n```\n\ngenerates\n\n```cs\npublic IRelayCommand\u003c(string text, bool isBusy)\u003e { get; }\n// Incorrectly omitted the nullable string\n// Should be `IRelayCommand\u003c(string? text, bool isBusy)\u003e`\n```\n\n## Reproduction Steps\n\n1. Download/clone the following repo: https://github.com/brminnick/ICommandAttribute_NullableParameter_Repro\n2. In Visual Studio, open `ICommandAttribute_NullableParameter_Repro.sln`\n3. In Visual Studio, Build/Run the solution\n\n## Reproduction Sample\n\nThe following code is also available in the following repo: https://github.com/brminnick/ICommandAttribute_NullableParameter_Repro\n\n### ViewModel\n\n```cs\npartial class ViewModel\n{\n    /*\n     *  // Auto-Generates The Following Code with the following bugs:\n     *   `string message` should be `string? messge`\n     *   `System.Collections.Generic.List\u003cstring\u003e stringList` should be `System.Collections.Generic.List\u003cstring\u003e? stringList`\n     *  \n     *  partial class ViewModel\n        {\n            /// \u003csummary\u003eThe backing field for \u003csee cref=\"M1Command\"/\u003e.\u003c/summary\u003e\n            [global::System.CodeDom.Compiler.GeneratedCode(\"CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator\", \"8.0.0.0\")]\n            private global::CommunityToolkit.Mvvm.Input.RelayCommand\u003c(global::System.DateTime? date, string message, bool? shouldPrint, global::System.Collections.Generic.List\u003cstring\u003e stringList)\u003e? m1Command;\n            /// \u003csummary\u003eGets an \u003csee cref=\"global::CommunityToolkit.Mvvm.Input.IRelayCommand{T}\"/\u003e instance wrapping \u003csee cref=\"M1\"/\u003e.\u003c/summary\u003e\n            [global::System.CodeDom.Compiler.GeneratedCode(\"CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator\", \"8.0.0.0\")]\n            [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]\n            public global::CommunityToolkit.Mvvm.Input.IRelayCommand\u003c(global::System.DateTime? date, string message, bool? shouldPrint, global::System.Collections.Generic.List\u003cstring\u003e stringList)\u003e M1Command =\u003e m1Command ??= new global::CommunityToolkit.Mvvm.Input.RelayCommand\u003c(global::System.DateTime? date, string message, bool? shouldPrint, global::System.Collections.Generic.List\u003cstring\u003e stringList)\u003e(new global::System.Action\u003c(global::System.DateTime? date, string message, bool? shouldPrint, global::System.Collections.Generic.List\u003cstring\u003e stringList)\u003e(M1));\n        }\n     */\n\n    [CommunityToolkit.Mvvm.Input.ICommand]\n    void M1((DateTime? date, string? message, bool? shouldPrint, List\u003cstring\u003e? stringList) parameter)\n    {\n        var (date, message, shouldPrint, stringList) = parameter;\n\n        if (shouldPrint is not false)\n        {\n            Console.WriteLine(message + date.ToString());\n\n            if (stringList is not null)\n            {\n                foreach (var text in stringList)\n                    Console.WriteLine(text);\n            }\n        }\n    }\n\n\n    /*\n    *  // Auto-Generates The Following Code with the following bugs:\n    *   `string message` should be `string? messge`\n    *   `System.Collections.Generic.List\u003cstring\u003e stringList` should be `System.Collections.Generic.List\u003cstring\u003e? stringList`\n    *  \n    *  partial class ViewModel\n    {\n        /// \u003csummary\u003eThe backing field for \u003csee cref=\"M2Command\"/\u003e.\u003c/summary\u003e\n        [global::System.CodeDom.Compiler.GeneratedCode(\"CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator\", \"8.0.0.0\")]\n        private global::CommunityToolkit.Mvvm.Input.AsyncRelayCommand\u003c(global::System.DateTime? date, string message, bool? shouldPrint, global::System.Collections.Generic.List\u003cstring\u003e stringList)\u003e? m2Command;\n        /// \u003csummary\u003eGets an \u003csee cref=\"global::CommunityToolkit.Mvvm.Input.IAsyncRelayCommand{T}\"/\u003e instance wrapping \u003csee cref=\"M2\"/\u003e.\u003c/summary\u003e\n        [global::System.CodeDom.Compiler.GeneratedCode(\"CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator\", \"8.0.0.0\")]\n        [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]\n        public global::CommunityToolkit.Mvvm.Input.IAsyncRelayCommand\u003c(global::System.DateTime? date, string message, bool? shouldPrint, global::System.Collections.Generic.List\u003cstring\u003e stringList)\u003e M2Command =\u003e m2Command ??= new global::CommunityToolkit.Mvvm.Input.AsyncRelayCommand\u003c(global::System.DateTime? date, string message, bool? shouldPrint, global::System.Collections.Generic.List\u003cstring\u003e stringList)\u003e(new global::System.Func\u003c(global::System.DateTime? date, string message, bool? shouldPrint, global::System.Collections.Generic.List\u003cstring\u003e stringList), global::System.Threading.Tasks.Task\u003e(M2));\n    }\n    */\n\n    [CommunityToolkit.Mvvm.Input.ICommand]\n    Task M2((DateTime? date, string? message, bool? shouldPrint, List\u003cstring\u003e? stringList) parameter)\n    {\n        var (date, message, shouldPrint, stringList) = parameter;\n\n        if (shouldPrint is not false)\n        {\n            Console.WriteLine(message + date.ToString());\n\n            if (stringList is not null)\n            {\n                foreach (var text in stringList)\n                    Console.WriteLine(text);\n            }\n        }\n\n        return Task.CompletedTask;\n    }\n}\n```\n\n```cs\nclass View\n{\n    public View()\n    {\n        var stringList = new List\u003cstring\u003e { \"Hello\", \"World\" };\n\n        var viewModel = new ViewModel();\n\n        // No warning/error\n        viewModel.M1Command.Execute((DateTime.UtcNow, \"Hello World\", true, stringList)); // No null values\n\n        // No warning/error\n        viewModel.M1Command.Execute((null, \"Hello World\", true, stringList)); // Pass `null` into Nullable struct\n\n        // Yes Nullable Warning/Error\n        viewModel.M1Command.Execute((DateTime.UtcNow, null, true, stringList)); // Pass `null` into Nullable string\n\n        // No warning/error\n        viewModel.M1Command.Execute((DateTime.UtcNow, \"Hello World\", null, stringList));  // Pass `null` into Nullable ValueType\n\n        // Yes Nullable Warning/Error\n        viewModel.M1Command.Execute((DateTime.UtcNow, \"Hello World\", true, null)); // Pass `null` into Nullable object\n\n\n        // No warning/error\n        await viewModel.M2Command.ExecuteAsync((DateTime.UtcNow, \"Hello World\", true, stringList)); // No null values\n\n        // No warning/error\n        await viewModel.M2Command.ExecuteAsync((null, \"Hello World\", true, stringList)); // Pass `null` into Nullable struct\n\n        // Yes Nullable Warning/Error\n        await viewModel.M2Command.ExecuteAsync((DateTime.UtcNow, null, true, stringList)); // Pass `null` into Nullable string\n\n        // No warning/error\n        await viewModel.M2Command.ExecuteAsync((DateTime.UtcNow, \"Hello World\", null, stringList)); // Pass `null` into Nullable ValueType\n\n        // Yes Nullable Warning/Error\n        await viewModel.M2Command.ExecuteAsync((DateTime.UtcNow, \"Hello World\", true, null)); // Pass `null` into Nullable object\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthecodetraveler%2Ficommandattribute_nullableparameter_repro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthecodetraveler%2Ficommandattribute_nullableparameter_repro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthecodetraveler%2Ficommandattribute_nullableparameter_repro/lists"}