Changes

→‎Changes: + Nullable reference type annotations
Line 139: Line 139:  
| <samp>IContentPack.GetActualAssetKey</samp>
 
| <samp>IContentPack.GetActualAssetKey</samp>
 
| Use <samp>ModContent.GetInternalAssetName</samp>, and remove the <samp>ContentSource</samp> parameter. This returns an <samp>IAssetName</samp> value; you can update your code to use that, or get the string value using its <samp>Name</samp> property.
 
| Use <samp>ModContent.GetInternalAssetName</samp>, and remove the <samp>ContentSource</samp> parameter. This returns an <samp>IAssetName</samp> value; you can update your code to use that, or get the string value using its <samp>Name</samp> property.
 +
|}
 +
 +
===Nullable reference type annotations===
 +
SMAPI is now fully annotated for [https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references C# nullable reference types]. This has no effect unless you enable them in your mod code too. If your mod does use them, you'll get helpful code analysis warnings from Visual Studio to avoid errors when null values are possible or prohibited. For example:
 +
<syntaxhighlight lang="c#">
 +
// warning: dereference of a possibly null reference
 +
var api = this.Helper.ModRegistry.GetApi<IExampleApi>("SomeExample.ModId");
 +
api.DoSomething();
 +
 +
// warning: possible null reference argument for parameter 'message'
 +
string? message = null;
 +
this.Monitor.Log(null);
 +
</syntaxhighlight>
 +
 +
Due to limitations in C# nullable reference annotations, a few edge cases aren't fully covered. These are documented in the code IntelliSense too.
 +
{| class="wikitable"
 +
|-
 +
! API
 +
! edge cases
 +
|-
 +
| <samp>helper.Reflection</samp>
 +
| The methods return values marked non-nullable, since they throw an error if the target isn't found. That doesn't change if you explicitly set <code>required: false</code>; in that case make sure to null-check the result anyway.
 +
|-
 +
| <samp>helper.Translation</samp>
 +
| Translations are marked non-nullable, since they fallback to the "''missing translation: key''" message. That doesn't change if you explicitly call <code>translation.UsePlaceholder(false)</code>; in that case make sure to null-check the text anyway if needed.
 +
|-
 +
| <samp>PerScreen&lt;T&gt;</samp>
 +
| This uses the nullability you set, like <code>PerScreen&lt;string&gt;</code> for a non-nullable string or <code>PerScreen&lt;string?&gt;</code> for a nullable one. However, calling the empty constructor with a non-nullable reference type will still create null values since that's the type default. For example:
 +
<syntaxhighlight lang="c#">
 +
var perScreen = new PerScreen<string>();
 +
string value = perScreen.Value; // returns null despite being marked non-nullable
 +
</syntaxhighlight>
 +
 +
To avoid that, you can specify the default non-nullable value to use:
 +
<syntaxhighlight lang="c#">
 +
var perScreen = new PerScreen<string>(() => string.Empty);
 +
string value = perScreen.Value; // returns empty string by default
 +
</syntaxhighlight>
 
|}
 
|}
    
[[Category:Modding]]
 
[[Category:Modding]]
translators
8,404

edits