昨天講了一下如何把代碼升級到 net6,今天我優化了好幾個小時更新代碼,enable了nullable。
c#的nullable我一直非常喜歡,它可以幫助開發人員,讓開發人員去思考,哪些地方需要可以為null,哪些地方不需要。它并不是萬能的靈丹妙藥,但是它的確可以大大的提高代碼質量。我自己通過在LuckyDraw里enable了nullable,從而發現了好幾個潛在的bug。現在一些其他語言,比如typescript也有類似功能,所以我覺得這個會是以后開發語言的一種趨勢。
這篇文章我來分享一下我遇到的一些nullable的問題,和如何解決的,希望對大家有一點點幫助。
首先,我們需要在csproj文件中加上?<Nullable>enable</Nullable>
?來讓編譯器知道我們希望打開nullable開關。
<Project Sdk="Microsoft.NET.Sdk.Web"><PropertyGroup><TargetFramework>net6.0</TargetFramework><LangVersion>10</LangVersion><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings></PropertyGroup>...
保存csproj文件后,稍等幾秒鐘后,你就會發現你的代碼里多了很多警告,這就是 c# 編譯器發現的一些可能是潛在的問題。
首先是和json相關的,比如:
var editForm = JsonSerializer.Deserialize<CompetitionEditForm>(str);
editForm.abc ...;
這里的warning在第二行,原因是?JsonSerializer.Deserialize<T>()
?的返回值可能為 null,所以我們不能直接就開始使用?editForm
,我們需要做一個判斷:
var editForm = JsonSerializer.Deserialize<CompetitionEditForm>(str);
if (editForm != null)
{editForm.abc ...;
}
當然這種改發稍微有點麻煩,每個地方都需要加上 if 判斷。我的做發是增加一個新的 method,如下:
public static class JsonHelper
{public static TValue Deserialize<TValue>(string json, JsonSerializerOptions? options = null){var value = JsonSerializer.Deserialize<TValue>(json, options);if (value == null){throw new Exception($"A non-null value is expected, but the result of Deserialize<{typeof(TValue).FullName}>() is null.");}return value;}
}
這樣我們確保我們這個方法不會返回 null,所以之前的代碼就可以改成下面這樣,沒有warning。
var editForm = JsonHelper.Deserialize<CompetitionEditForm>(str);
editForm.abc ...;
另外還有一塊也是和json相關的,因為目前teams bot sdk還是使用Newtonsoft.JSON,所以我們的teams app里還是有很大一部分代碼還是會和 Newtonsoft.JSON 發生關系。比如:
public static string GetBotMessagePreviewAction(this Activity activity)
{var value = (JObject)activity.Value;var botMessagePreviewAction = (string)value.GetValue("botMessagePreviewAction");return botMessagePreviewAction;
}
因為 activity 的 Value 是 JObject,而 JObject 的 GetValue() 可能會返回空,所以上面的代碼需要對 botMessagePreviewAction 進行是否為 null 的判斷。不過因為我在其他地方做過判斷,只要調用這個方法,就說明 JObject 里肯定有?botMessagePreviewAction
?這個屬性。所以我采用了一個簡單的改法,使用?!
,在語句最后加了?!
,來告訴編譯器,我確定不會為 null。
var botMessagePreviewAction = (string)value.GetValue("botMessagePreviewAction")!;
上面只是在我的項目里遇到的兩個常見問題,以及我的修改方法。僅供參考。