{"id":1234,"date":"2026-10-26T09:20:26","date_gmt":"2026-10-26T09:20:26","guid":{"rendered":"https:\/\/docs.sisus.co\/init-args\/?p=1234"},"modified":"2026-10-26T09:20:26","modified_gmt":"2026-10-26T09:20:26","slug":"optional-init-arguments","status":"publish","type":"post","link":"https:\/\/docs.sisus.co\/init-args\/advanced\/optional-init-arguments\/","title":{"rendered":"Optional Init Arguments"},"content":{"rendered":"<h1>What Are Optional Init Arguments?<\/h1>\n<p>By default Init(args) assumes that every Init argument a client receives is required. If an argument is missing, and the <a href=\"https:\/\/docs.sisus.co\/init-args\/initializers\/null-argument-guard\/\">Null Argument Guard<\/a> is enabled, you get warnings shown in the Inspector, logged to the Console in Edit Mode and exceptions thrown at runtime.<\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-full wp-image-1238\" src=\"https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/missing-init-argument.png\" alt=\"\" width=\"432\" height=\"143\" srcset=\"https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/missing-init-argument.png 432w, https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/missing-init-argument-300x99.png 300w\" sizes=\"(max-width: 432px) 100vw, 432px\" \/><\/p>\n<p>Sometimes, however, you might want to create a client that can work perfectly fine without receiving some of its dependencies from the outside through its Init method. For example, a component might log messages using a logger injected through its Init method when provided one, but fallback to using a default logger implementation if none has been provided.<\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-full wp-image-1237\" src=\"https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/client-optional-init-argument.png\" alt=\"\" width=\"416\" height=\"110\" srcset=\"https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/client-optional-init-argument.png 416w, https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/client-optional-init-argument-300x79.png 300w\" sizes=\"(max-width: 416px) 100vw, 416px\" \/><\/p>\n<p>You can let Init(args) know about such optional Init arguments by marking them as nullable.<\/p>\n<h1>Marking Init Arguments Optional<\/h1>\n<p>There are a couple of different ways to let Init(args) know that an Init argument is optional. They all have the same effect, so you can use whichever one you prefer.<\/p>\n<h2>Nullable Reference Types<\/h2>\n<p>If you have <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/csharp\/nullable-references\">nullable reference types<\/a> enabled, you can make the Init parameter have a nullable type:<\/p>\n<pre>#nullable enable\r\nusing Sisus.Init;\r\n\r\nclass Enemy : MonoBehaviour&lt;IPlayer, ILogger&gt;\r\n{\r\n    IPlayer player = null!;\r\n    ILogger logger = null!;\r\n\r\n    protected override void Init(IPlayer player, ILogger<strong>?<\/strong> logger)\r\n    {\r\n        this.player = player;\r\n        this.logger = logger ?? new DefaultLogger();\r\n    }\r\n}<\/pre>\n<h2>[AllowNull] Attribute<\/h2>\n<p>Add the <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.diagnostics.codeanalysis.allownullattribute\">[AllowNull]<\/a> attribute to the parameter:<\/p>\n<pre>using System.Diagnostics.CodeAnalysis;\r\nusing Sisus.Init;\r\n\r\nclass Enemy : MonoBehaviour&lt;IPlayer, ILogger&gt;\r\n{\r\n    IPlayer player;\r\n    ILogger logger;\r\n\r\n    protected override void Init(IPlayer player, <strong>[AllowNull]<\/strong> ILogger logger)\r\n    {\r\n        this.player = player;\r\n        this.logger = logger ?? new DefaultLogger();\r\n    }\r\n}<\/pre>\n<h2>Default Value Of Null<\/h2>\n<p>Give the parameter in the <code>Init<\/code> method a default value of <code>null<\/code>:<\/p>\n<pre>using Sisus.Init;\r\n\r\nclass Enemy : MonoBehaviour&lt;IPlayer, ILogger&gt;\r\n{\r\n    IPlayer player;\r\n    ILogger logger;\r\n\r\n    protected override void Init(IPlayer player, ILogger logger = null)\r\n    {\r\n        this.player = player;\r\n        this.logger = logger;\r\n    }\r\n}<\/pre>\n<h2>Initializer Init Class<\/h2>\n<p>If you have an <a href=\"https:\/\/docs.sisus.co\/init-args\/initializers\/initializer\/\">Initializer<\/a> with a nested <code>Init<\/code> class, you can make the field that corresponds with the Init argument have a nullable type or add the <code>[AllowNull]<\/code> or <code>[MaybeNull]<\/code> attribute to it to mark it as optional:<\/p>\n<pre>#nullable enable\r\nusing Sisus.Init;\r\n\r\nclass EnemyInitializer : CustomInitializer&lt;Enemy, IPlayer, ILogger&gt;\r\n{\r\n    class Init\r\n    {\r\n        IPlayer Player = default;\r\n        ILogger? Logger = default;\r\n    }\r\n\r\n    protected override void InitTarget(Enemy enemy, IPlayer player, ILogger? logger)\r\n    {\r\n        ((IInitializable&lt;IPlayer, ILogger&gt;)enemy).Init(player, logger ?? new DefaultLogger());\r\n    }\r\n}<\/pre>\n<p>This can be useful when assigning the argument is optional when the client is configured using this particular initializer, but not necessarily in other situations.<\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-full wp-image-1236\" src=\"https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/initializer-optional-init-argument.png\" alt=\"\" width=\"416\" height=\"109\" srcset=\"https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/initializer-optional-init-argument.png 416w, https:\/\/docs.sisus.co\/init-args\/wp-content\/uploads\/sites\/6\/2026\/10\/initializer-optional-init-argument-300x79.png 300w\" sizes=\"(max-width: 416px) 100vw, 416px\" \/><\/p>\n<h1>What Changes?<\/h1>\n<h2>Inspector<\/h2>\n<p>When an optional Init argument is missing, no warning is shown about it in the Inspector, even when Null Argument Guard is enabled.<\/p>\n<p><!-- SCREENSHOT: Init section of a client with one required argument showing \"Not Found\" (tinted) and one optional argument showing \"Null\" (not tinted). --><\/p>\n<p><!-- SCREENSHOT: Initializer with an empty optional argument field (not tinted) next to an empty required argument field (tinted red). --><\/p>\n<h2>Edit Mode<\/h2>\n<p>When an optional Init argument is missing, no warning is logged to the Console in Edit Mode, even when Null Argument Guard is enabled.<\/p>\n<h2>Runtime<\/h2>\n<p>When the client receives <code>null<\/code> for an optional argument, no <code>InvalidInitArgumentsException<\/code> is thrown. This is the case regardless of whether the arguments are passed to the client by an Initializer, or manually in code:<\/p>\n<pre>gameObject.AddComponent&lt;Enemy, IPlayer, ILogger&gt;(player, null);<\/pre>\n<h2>Async Initialization<\/h2>\n<p>When an optional Init argument is missing when the client is loaded, the client does not wait in a disabled state for it to become available, even if it has been <a href=\"https:\/\/docs.sisus.co\/init-args\/reference\/init-attribute\/\">configured to wait for services<\/a> using <code>[Init(WaitForServices = true)]<\/code>.<\/p>\n<h1>Handling Optional Dependencies<\/h1>\n<p>Since an optional argument can be <code>null<\/code>, the client must be ready to handle that situation.<\/p>\n<p>One option is to check for null every time before using the dependency:<\/p>\n<pre>void Attack()\r\n{\r\n    player.TakeDamage(damage);\r\n    logger?.Log($\"{name} attacked the player.\");\r\n}<\/pre>\n<p>Another option is to replace the missing dependency with a fallback instance during the client&#8217;s initialization:<\/p>\n<pre>protected override void Init(IPlayer player, ILogger? logger = null)\r\n{\r\n    this.player = player;\r\n    this.logger = logger ?? new NullLogger();\r\n}<\/pre>\n<h1>Default Values<\/h1>\n<p>If an Init parameter is given a default value other than <code>null<\/code>, that value is used as the initial value of the argument when an Initializer is attached to the client:<\/p>\n<pre>class Enemy : MonoBehaviour&lt;IPlayer, float&gt;\r\n{\r\n    protected override void Init(IPlayer player, float moveSpeed = 5f)\r\n    {\r\n        ...\r\n    }\r\n}<\/pre>\n<p>A field initializer in the nested <code>Init<\/code> class of a custom Initializer can be used for the same purpose, and takes precedence over the Init parameter&#8217;s default value when the initializer in question is attached to the client:<\/p>\n<pre>class EnemyInitializer : Initializer&lt;Enemy, IPlayer, float&gt;\r\n{\r\n    class Init\r\n    {\r\n        IPlayer Player = default;\r\n        float MoveSpeed = 10f;\r\n    }\r\n}<\/pre>\n<h1>Optional Init Arguments vs Optional Initialization<\/h1>\n<p>Marking an Init argument optional only affects that one argument; the Null Argument Guard can still keep protecting all the other arguments of the client.<\/p>\n<p>If you want to allow a component to be loaded without it receiving any dependencies in its Init method at all, you can use <code>[Init(Enabled = false]<\/code> instead. See <a href=\"https:\/\/docs.sisus.co\/init-args\/reference\/init-attribute\/\">[Init] attribute<\/a> for more information.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What Are Optional Init Arguments? By default Init(args) assumes that every Init argument a client receives is required. If an argument is missing, and the Null Argument Guard is enabled, you get warnings shown in the Inspector, logged to the Console in Edit Mode and exceptions thrown at runtime. Sometimes, however, you might want to ..<\/p>\n<div class=\"clear-fix\"><\/div>\n<p><a href=\"https:\/\/docs.sisus.co\/init-args\/advanced\/optional-init-arguments\/\" title=\"read more\">Read more<\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/1234"}],"collection":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/comments?post=1234"}],"version-history":[{"count":8,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/1234\/revisions"}],"predecessor-version":[{"id":1245,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/1234\/revisions\/1245"}],"wp:attachment":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/media?parent=1234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/categories?post=1234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/tags?post=1234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}