はつねの日記

Kinect, Windows 10 UWP, Windows Azure, IoT, 電子工作

Xamarinで作成したAndroid App Bundleを端末にインストールする

2021年8月からは、Google Playに新しくアプリを登録するには、従来のapkではなくAndroid App Bundle(aab)で登録することが必要になります。
Visual Studio + XamarinでAndroid向けアプリを作成するときも、もちろん、apkだけではなくaabで作成できます。
初期のころはaab作成がVisual Studioからはできず、MSBuildを使ってコマンドラインでaabファイルをつくらなければなりませんでしたが、最近のVisual Studioではアーカイブでも可能です。

Androidオプションを設定する

aabを作成するには、Androidアプリのプロジェクトのプロパティを表示して、Androidオプション画面で設定します。
aab作成には本当に時間がかかるので、Release構成のみの設定が推奨されています。

Release構成で設定する

そのため、[構成]を「Release」にしてから設定を変更します。
f:id:hatsune_a:20210218073903p:plain
設定は簡単で、Androidパッケージ形式を「バンドル」にするとaab作成となります。このとき次の2つのチェックボックスが、値固定でグレーアウトします。

  • [選択したABIごとに1つのパッケージにします]はOFF
  • [インクリメンタルAndroidパッケージシステム(aapt2)を使用します]はON
aapt2とは

aapt2(Android Asset Packaging Tool)は、アプリのリソースをコンパイル、パッケージ化するために使用するビルドツールです。AAPT2 はリソースを解析してインデックスに登録し、Android プラットフォーム向けに最適化されたバイナリ形式にコンパイルします。

Debug構成で設定する

2つの設定が固定化されるのであれば、Debug構成でも同じ設定にしておいてデバッグしておくことが安全です。
aapt2については新規プロジェクト作成時はデフォルトONになっていますが、以前から使っているプロジェクトではOFFになっているものも多いでしょう。
それでは、[構成]を「Debug」にしてaapt2をONに設定しましょう。
f:id:hatsune_a:20210218075244p:plain
Visual Studioが至れり尽くせりだなーと思うのは、Release構成側で「バンドル」を指定すると、Debug構成側も自動的に2つのチェックボックスが同じ値でグレーアウトしていました。
もちろん、パッケージ形式は「apk」のままです。

アーカイブを実行する

構成ごとの設定がおわったら、Release構成をアクティブにしてアーカイブします。
f:id:hatsune_a:20210218080119p:plain
アーカイブが成功すると、アーカイブマネージャーにバンドル形式「aab」のエントリが表示されます。
f:id:hatsune_a:20210218080434p:plain

配布用に署名する

アーカイブができたら、[配布]ボタンをクリックして「アドホック」でファイル作成して手動でGoogle Play Consoleにアップロードするか、「Google Play」でアップロードまで行うかを選んで、署名付きaabを作成します。
実機にインストールするためには、「アドホック」を選択して署名付きaabファイルを作成しましょう。

aabを実機にインストールする

署名付きaabを実機にインストールしたいときは、adbコマンドを使って実行します。
f:id:hatsune_a:20210218100427p:plain
Visual Studioのメニューからコマンドラインを起動して、USBに実機を接続してUSBデバッグを許可したらadb installします。
f:id:hatsune_a:20210218100918p:plain
Successが出たら終了です。
実機で動作を確認してみましょう。

Google Play Consoleにアップロードする

実機確認できたら、署名付きaabをGoogle Playに登録してみましょう。
試しに、登録済のapkと同じバージョンとバージョンコードで作成して登録してみると次のようなエラーとなりました。
f:id:hatsune_a:20210218090633p:plain
当然ですが、apkとaabで同じバージョンをアップロードはできないようですね。

Google Playでアプリを署名する

ついでといっては何ですが、配布するならば「Google Playで署名されています」マークを付けておきたいですよね。
新規に登録するときは自動的にGoogle Play Consoleで次のような表示になります。
f:id:hatsune_a:20210218090543p:plain
既存登録済でこの表示がない場合は、手動で設定しないといけないのですが、次のQuitaが分かりやすかったです。
qiita.com
qiita.com
上から順番に読んでみると理解しやすくお勧めです。

それではVisual StudioでのAndroidアプリ開発、楽しんでいきましょう!

NAudioをUWPで使うときの注意点

以下、NAudio v1.10での確認となります。
NAudioですが、音声入出力に非常に便利なライブラリで、.NET Framework以外にも様々なプラットフォームで動作します。
github.com

しかし、UWPで使用する場合、いつくかの注意点があります。

.NETネイティブコンパイル時の注意点

それは、ARM / ARM64に限らずx86をプラットフォームターゲットとしたときも.NETネイティブコンパイル時には次のような実行時エラーが発生します。

System.ArgumentException: 'Unsupported Wave Format'

この実行時エラーは、NAudioのサンプルコードでNAudioUniversalDemoがあるので、そちらで確認することができます。
このサンプルコードを.NETネイティブコンパイルして実行して「Record」ボタンをクリックすると、NAudioの中、具体的には、NAudio.Wave.WasapiCaptureRT.InitializeCaptureDeviceの中で下記のエラーが発生します。
こちらは録音デバイスがサポートしていないWaveフォーマットを指定したからだということです。
こちら、.NETネイティブではないときには、WaveFormatとしてサンプリングレート48000、32ビット、1チャンネルのIeeeFloatなフォーマットが自動的に指定されますが、.NETネイティブコンパイル時はその自動指定が行われず、ソースコードを読む限りはAudioClient.csの中のpublic WaveFormat MixFormatプロパティのGetの中でaudioClientInterface.GetMixFormatのところで取得ができていないようです。

注:Visual Studio 2019を使用し、ターゲットバージョン=2004 (ビルド19041)、最小=1803(ビルド17134)を指定

.NETネイティブコンパイルは必須

それでは、.NETネイティブコンパイルしなければいいのでは?となりますが、ストアに登録して配布するときは.NETネイティブコンパイル必須となっているので、配布手段はどうあれ.NETネイティブコンパイルで動作しないというのは、今後を考えると避けたいところです。

対応策

対応策としては、サンプルコードNAudioUniversalDemoでいえばMainPageViewModel.csのなかでrecorder.StartRecording()を実行する前に、明示的にWaveFormatを指定してしまうことです。
NAudio/MainPageViewModel.cs at master · naudio/NAudio · GitHub

recorder.WaveFormat = new WaveFormat(48000, 32, 1);

なお、この場合、IeeeFloatではなくPCMのサンプリングレート48000、32ビット、1チャンネルとなります。
また、万が一、指定したサンプリングレートおよびチャンネル数が、該当のデバイスでサポートしていない録音デバイスだったときも実行時エラーとなります。
こうなってくるとストアに登録して広く公開するのはなかなか難しい状況だといえるでしょう。
例えば、ARM64 Windows機のLenovo C630のInternal Microphoneは、サンプリングレート48000Hz、16ビット、1チャンネルですが、インテルWindows機だと2チャンネルの場合があります。

解決方法

解決補法としては3つ

  1. NAudioを使わない方法を考える
  2. ストア配布対象をx86に絞る
  3. NAudioのMixFormat取得ロジックを.NETネイティブ対応する

まずは、1か2の検討をして、なんとか3が解決される(もしくはOSSなので自力で解決してプルリクする)のを待つ形になります。

本当の解決を目指して

NAudioのMixFormat取得ロジックは.NETネイティブコンパイルしていないときと、.NETネイティブコンパイルしたときではどのように違うか確認してみましょう。
NAudioのGitHubからソースコードを取得して、AudioClient.csのMixFormatクラスにブレイクポイントを貼って、デバッグ実行をしてみます。

非.NETネイティブコンパイル時の動き

48000Hz、16bit、2チャンネルの録音デバイス
非ネイティブのときは、MixFormatの戻り値は、サンプリングレート48000Hz、32bit PCM、2チャンネルとなります。

{32 bit PCM: 48kHz 2 channels wBitsPerSample:32 dwChannelMask:3 subFormat:00000003-0000-0010-8000-00aa00389b71 extraSize:22}
AverageBytesPerSecond: 384000
BitsPerSample: 32
BlockAlign: 8
Channels: 2
Encoding: Extensible
ExtraSize: 22
SampleRate: 48000
SubFormat: {00000003-0000-0010-8000-00aa00389b71}
averageBytesPerSecond: 384000
bitsPerSample: 32
blockAlign: 8
channels: 2
dwChannelMask: 3
extraSize: 22
sampleRate: 48000
subFormat: {00000003-0000-0010-8000-00aa00389b71}
wValidBitsPerSample: 32
waveFormatTag: Extensible

この中のsubFormatの値がWAVE_FORMAT_IEEE_FLOATを意味しています。
この内部値は外から見えないので、外から見えるrecorder.WaveFormatの値を見てみましょう。
こちらは、IeeeFloatとして取り出せます。

{IeeeFloat}

WaveFormat未指定時に本来期待されている動きは、この動きになります。

.NETネイティブコンパイル時の動き

それでは.NETネイティブコンパイルしたときの値をみてみましょう。
MixFormatの戻り値は、サンプリングレート48000Hz、32bit PCM、2チャンネルとなりますが、クラスの型値がExtensibleのままでPCM表記になりません。

{NAudio.Wave.WaveFormatExtensible}
AverageBytesPerSecond: 384000
BitsPerSample: 32
BlockAlign: 8
Channels: 2
Encoding: Extensible
ExtraSize: 22
SampleRate: 48000
SubFormat: {System.Guid}
averageBytesPerSecond: 384000
bitsPerSample: 32
blockAlign: 8
channels: 2
dwChannelMask: 3
extraSize: 22
sampleRate: 48000
subFormat: {System.Guid}
wValidBitsPerSample: 32
waveFormatTag: Extensible

値を確認すると今回の原因はSubFormatにWAVE_FORMAT_IEEE_FLOATを意味する値が入っていないことがわかりました。
しかしここで注目すべきは、サンプリングレート、ビット数、チャンネル数などは取得ができてる点です。もしこれらの値を取得できれば、new WaveFormat(48000,32,1)のように指定してNAudioに該当録音デバイスのフォーマットが指定できることになります。

さあ、NAudioを書き換えよう

NAudioの内部状態のところでエラー判定されているので、NAudioの外側からどうにかできる問題じゃなさそうです。
そうなってくるとNAudioのどのクラスで対応するかですが、UWPのみの問題だと考えると、WasapiCaptureRTクラスの中で対応するのがよさそうです。

gist.github.com

audioClient.MixFormatメソッドの戻り値を変数名mixにいれて、それがWaveFormatExtensibleであればビット数に応じてIeeeFloatかPCMか明示してフォーマットを作成することにします。
例えば、先ほどの48000Hz、16bit、2チャンネルの録音デバイスであれば、内部変数のwaveFormatは下記のようにIeeeFloatとして処理される内容になります。

{NAudio.Wave.WaveFormat}
AverageBytesPerSecond: 192000
BitsPerSample: 32
BlockAlign: 4
Channels: 1
Encoding: IeeeFloat
ExtraSize: 0
SampleRate: 48000
averageBytesPerSecond: 192000
bitsPerSample: 32
blockAlign: 4
channels: 1
extraSize: 0
sampleRate: 48000
waveFormatTag: IeeeFloat

このオリジナルのNAudio.dllは、Releaseビルドすれば、NAudio\bin\Release\uap10.0フォルダに出力されます。
自分のUWPプロジェクトでnugetではなくからそのDLLを参照するように切り替えれば、.NETネイティブコンパイルしたUWPアプリも正常にNAudioが動作します。
どうせならばと、この件は本家にプルリクしてみました。

Azure Web Appsのランタイムスタックの分類について

[en]
When I try to create a web app in Azure and try to specify the runtime stack, I get the following message.
f:id:hatsune_a:20210104130352p:plain
I think ”.NET 5" should be on the ".NET Core" side, but what do you think?

    • -

[jp]
AzureでWebアプリを作成しようとしてランタイムスタックを指定しようとすると以下のような表示になります。
f:id:hatsune_a:20210104130352p:plain
「.NET 5」は、「.NET Core」側にあった方がよいと思うのですが、どうでしょうか。

      • -

UWPアプリでFilePickerで指定したファイルをリスト表示する

2DなUWPアプリで一覧表示したボタンをクリックすると、FilePickerでファイルを指定してその行に画像を表示したいという質問を頂いたので、まとめます。
なお、少々手抜きをしていて、Modelの中でFilePicker起動しちゃってます。
本来であれば、イベントあたりを使って、ModelじゃなくてViewとかに通知を伝搬して、そこでFilePickerを呼び出して、ファイルから画像設定のModelをView→ViewModel→Viewという感じに読んであげるのがいいような気がします。

UWPに権限を追加する

f:id:hatsune_a:20201127145000p:plain

一覧表示用クラスを定義する

gist.github.com
ボタン押した行をイベントとして外に通知して、外側のImageModelクラスでImageSourceを設定した感じに変えた方がいいと思います。
※後日変えると思います

Modelを定義する

gist.github.com

ViewModelを定義する

gist.github.com

Viewを定義する

gist.github.com

gist.github.com

デジタルインナーミラー ドラレコ AC80を買いました

最近は楽しいドライブの必須アイテム感も増してきちゃいましたドラレコことドライブレコーダーですが、そのお陰か「ほしい!」と思えるようなスペックの製品が意外とお値打ち価格で手に入りようになりました。

今回、購入したのは、AUTOSOCTさんのAC80というバックミラーにかぶせる感じで取り付けることができるドラレコです。


この製品が気に入ったのは次の点です。

  • ミラーに取り付けるのでフロントウィンドウに張り付けるもののように落下の心配がないし、ダッシュボード上とか視界に入らない
  • 右ハンドル仕様で右側にフロントカメラがあり、また、ミラーを運転席側に向けることを前提とした視野となっている
  • バックカメラもある2カメラ構成である
  • フロント2Kカメラで奇麗、バックカメラも1080p
  • HDRなので夜間なども白飛びせずにナンバープレートが撮影できる
  • GPS内蔵なので走行記録がWindows PCであとで見られる

フロントカメラだけなら、ミラーにつけてあとはシガーソケットから電源をとるだけで簡単設置できるのも手軽かもしれませんが、今回、ドラレコを設置するにあたって自分に課したミッションとしては「電源はヒューズボックスから」「配線は極力隠す」「バックカメラもつける」がありましたので、まずはそれに必要なものを追加でそろえましょう。

製品スペック

サイズ:168mm x 81mm x 40mm
重量:1100g
記録メディア:Class 10以上のMicroSD / 32GB~128GB
スクリーンサイズ:12インチ
ビデオフォーマット:MP4
写真フォーマット:JPEG
フロント視野:170度
解像度:2K + 1080p
電源:5V / 2.5A

取付準備

グローブ

まずはグローブですね。以前から愛用している整備用のものです。ピッタリ手にフィットする感じが素敵。耐熱だし絶縁だしで安全ですね。ただ、スマホ操作できないので記録用写真撮るたびに外すのが若干面倒です。

内張りはがし

今回の作業を行ってみて「必須!」だと思った道具の一つがこちらの内張はがし。いろいろなシーンで大活躍です。これを持たずして内装周りの作業しちゃダメだと思いました。

ハーネス結束&保護テープ

そして、もう一つの必須アイテムが、この保護テープ。エーモンさん様々ですね。どんな感じで使ったのかは、取付StepByStepの中でご紹介します。

電源ソケット DC12V/24V60W以下 ヒューズ電源タイプ

あとは、ドラレコ電源が、シガーソケットタイプだったので、そこからヒューズボックスからとれるように変換ケーブルですね。
電源自体は5V/2.5Aなので、付属の5Aの管ヒューズをもうちょっと小さいアンペアのものにしてあげてもいいかもしれなないですね。

取付StepByStep

ヒューズボックスの確認

まずはヒューズボックスを開けて、車のマニュアルと照らし合わせてどこのヒューズから分岐するかを検討します。

ライトやそのほか、車の運航に必要なヒューズは避けた方がいいので、そうなってくると一番おすすめはカーオーディオ用のヒューズからの分岐です。

プジョー206では、写真で下から2段目、左から3つめ(No.24)の15Aのヒューズが該当します(年式によって違うようですので車付属の説明書で確認しましょう)。
このヒューズ位置ですが、段差を合わせえるとACC、つまり、アクセサリー電源といってキーを一段回した段階で電源がONになります。カーナビやカーオーディオ、ETCなどがそうですね。
一方、写真のように半段づらしていると、常時電源になります。
24H駐車監視と衝撃判断でファイルロックもできる機能がついているので、駐車中もドラレコで録画できるようにするためには、常時電源にしておきましょう。
逆にほとんど乗らないしということであればACC電源にしておくのもいいですね。

メモ代わりに記載ですが、隣のNo23の黄色い20Aがシガーソケットです。タバコ吸わないのでシガーソケットは思うにスマホ充電用なので、ついでにこっちは半段下げてACC電源にしておきました。

本体をミラーに取り付ける

ワイドミラーを付けていたのでそれをサクッとはがして、代わりにドラレコ本体を付けます。

いままでつけていたワイドミラーはバネの力でカチッとはまってくれていて、新車購入時から1度も落下することなく今回まで活躍してくれてました。
一方、今回のドラレコは重量が1100gあるのですが、ゴムで止めるタイプ。で、このゴムは劣化するらしくて時々交換しないとらしいです。

このあたりを割り切りと考えるかどうかもあるかもしれないです。
ただ、できれば、数千円高くなってもバネでカチッととめられたらよかったかな。これ結束バンドとで代替できるか、そのうち試したいですね。

Aピラーの内装をはがす

車には、天井を支えるピラーと呼ばれるものには、フロントウィンドウとサイドウィンドウの間のAピラー、前部座席と後部座席の間のBピラー、後部座席とリアウインドウの間のCピラーなどがあります。
つまり、Aピラーとはフロントウィンドウの端っこにあるピラーになります。
f:id:hatsune_a:20201121143011p:plain
今回のドラレコはバックミラーに設置するタイプなので、バックミラーからAピラーまでケーブルを這わせて、ダッシュボード上のGPSユニットまでのケーブルとヒューズボックスまでの電源ケーブルの2本について、Aピラーを通していきます。
そのため、まずは、Aピラーの内張をぺりっとはがします。
上の部分に指をひっかけて、手前に引っ張ると上から順番に外れるような構造になっています。最後は、ダッシュボードの隙間からサクッと抜き出す感じです。

ミラー位置から電源、GPSケーブル、バックカメラケーブルを内装に押し込む

電源、GPSケーブル、バックカメラケーブルを「ハーネス結束&保護テープ」を使って1つにまとめます。

まとめたケーブルをバックミラーの背後から運転席側のフロントウィンドウと天井内装の隙間に「内張はがし」を使ってケーブルをぐぐっと押し込んでいきます。

写真の左側のところをつかって狭い隙間もらくらくに押し込めます。
マイナスドライバーでも可能かもしれないですが、このオレンジのは材質が柔らかいのでケーブルなども傷つけることなく作業ができるので、余計な心配せずにすごく捗りました。
最後はこんな感じに事前に剥がしておいたAピラーのところにでてきます。
f:id:hatsune_a:20201121143349p:plain

Aピラーにケーブルを這わす

f:id:hatsune_a:20201121143517p:plain
Aピラー内部には、ケーブルが止められるような構造になっています。内張りもここにはまっていますので、内張りの足がはまるところ以外をつかってケーブルを挟んでいきましょう。
こうやって挟んでおかないと後々走行時にカタカタ音が鳴る原因となりますのでちゃんとやります。
ここでも「ハーネス結束&保護テープ」が活躍します。ちょうど止める部分に巻くことでよい感じのテンションがかかってくれます。

ダッシュボードの中を通してヒューズボックスへ

Aピラーを通し終えたら、ここで、GPSケーブルと電源ケーブルはお別れです。
GPSケーブルは、そのまま、こんどはダッシュボードとフロントウィンドウの隙間に押し込んで、ダッシュボード上のGPSユニットまでつないでいきます。

一方、電源ケーブルは、ダッシュボードの中に押し込みながらヒューズボックスを目指します。
f:id:hatsune_a:20201121143911p:plain

シガーソケットタイプからヒューズタイプへ変換

f:id:hatsune_a:20201121144113p:plain
変換ケーブルを使って平形ヒューズに電源を変更します。この変換ケーブルですが、ボディアースが必要なので、ヒューズボックス周りにあるボディアースポイントが必要です。
電気周りの作業をするので事前にバッテリー端子を片方外して、通電されないようにしておきましょう。

ボディアース

ボディアースポイントは、ヒューズボックスの奥にあって、ヒューザボックスを外さないと手が入らないところにあります。
これは外すかとおもってみたらダッシュボードのサイドにボディアースポイントにアクセスするためのメンテ口があるじゃないですか。内張はがしでサクッとはずすせば簡単にアースできました。

f:id:hatsune_a:20201121144355p:plain
f:id:hatsune_a:20201121144518p:plain

ヒューズ接続

f:id:hatsune_a:20201121145514p:plain
15Aのヒューズを差し替えてあげることで、15Aのヒューズの役割はそのままで、そこからドラレコ電源へ分岐ができました。ドラレコ電源自体は管ヒューズを経由してなので、そっちで過電流がながれたら管ヒューズがきれてくれる仕組みです。

AピラーからCピラーを目指す

Aピラーの上端で、分岐したもう一つのケーブルであるバックカメラケーブルはドア上と天井内張りの間を「」でこれまた押し込まれながらリアを目指します。
途中Bピラーがあるのですが、これも上端からケーブルが押し込められました。ほんと、フランス車なのかはわかりませんが、良い加減な感じな構造ですね。
f:id:hatsune_a:20201121145910p:plain

Cピラーからハッチバックドアへ

Cピラーまできたら、この先どのように進むかはバックカメラをどこにつかるかによります。
多分、ナンバープレートあたりに着けるのがよいと思うのですが、今回の車は、ナンバープレートが後ろのハッチバックドアと一緒になっているタイプなので、天井内張りからCピラーを下に進むのではなくハッチバックドアに進みます。
f:id:hatsune_a:20201121150035p:plain
ここは可動部なのと、そして、ハッチバックドア側には内張りがないので「ハーネス結束&保護テープ」でドアの開け閉めに引っ張られず、また、ドアが噛まないような長さで止めることにしました。

本当は、反対側には車体とハッチバックドアの間を通っているケーブルの通り道があるので、リアの天井内張りを通って反対側に抜けてそっちからハッチバックドアに進むのがいいのかもしれません。今度、時間をみつけて経路変更するかも。
ただし、今回のルートでもリアウィンドウ下には電熱ヒーター線の口があって、そこからハッチバックドア内部にいけるので、今回は、このルートからドアの中にいれました。
f:id:hatsune_a:20201121150458p:plain

車外へ

最初、車内にリアカメラを設置したのですが、リアウィンドウの反射が映りこんでしまうので、最終的にはナンバープレート脇に設置しました。
そのため、リアカメラケーブルは、最後は車外に出さないといけないのですが、難波プレート周りに車外にアクセスするための穴がどこにも開いていないのです。ナンバープレート灯あたりから通せるかとおもったら隙間なさそうだし、ハッチバックドアのドアノブもダメってことで、ドア下を通して、そこからナンバープレートと車体の隙間をとおって(ここでも内張りはがしの押し込みが活躍)リアカメラにつなぎました。
f:id:hatsune_a:20201121151236p:plain

結果的にはこの位置で正解ですね。
f:id:hatsune_a:20201121151505p:plain
信号待ちで直後に止まってくるまのナンバープレートもばっちり入ります。

まとめ

これって、ホロラボの「TebanashiManual」とかあるとマニュアルと現物両方見ながら確認できたり、「TechniCapture」があればプロの整備士さんの手順と目線で作業ができるんだろうなーと思いました。
すくなくとも「これどこー」とか「これであってるんだろうか?」的な不安感はだいぶなくなるんだろうなと小春日和な中で作業を終えた後の缶コーヒーを飲みながらしみじみ思った1日でした。
hololab.co.jp
hololab.co.jp

I started ".NET 5"

This entry is an English translation of the ".NET 5始めました! - はつねの日記" entry

[en]NET 5 has been released.

dotnet.microsoft.com
Even if you don't download the SDK or anything else separately, Visual Studio 2019 will also update to 16.8.1, which is a form of development environment that includes .NET 5.
Therefore, if you are starting out with .NET 5, we recommend that you update Visual Studio 2019 rather than downloading it individually.
Now you have a choice between .NET Core 2.1 LTS / .NET Core 3.1 LTS / .NET 5.
And if you want to create in WPF, you can use .NET Core 3.1 LTS or .NET 5.
Let's pick out some of the most interesting changes in .NET 5.

C# 9.0

In .NET 5, C# 9.0 is available.
C# 9.0 の新機能 - C# ガイド | Microsoft Docs

Top-level statement

From now on, if you want the console to say "Hello World!
>> "Hello World!
System.Console.WriteLine("Hello World!");<< "Hello World!

**

If you want to initialize a variable at the same time as declaring it, you have to write the type name on the right and left side of the equalizer in the same way, for example, if you cannot use var.
From now on, you can write only the left side and the right side can be written as "new()" without the type name. Simple.

private List _observations = new();
_observations = new();
This is because the left side is omitted, it feels the same as var, so my personal opinion is that I would have been happier if the type name on the left side was omitted.

The changes when creating a WPF app

WPF SDK (Microsoft.NET.Sdk.WindowsDesktop) has been changed to .
Sdk. If you do not change, you will see a compile-time warning.
If you have changed the target of your .NET Core 3.1 project to .NET 5, you can use the csproj file to create a .
>> The
Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"

Where the
>> The
Project Sdk="Microsoft.NET.Sdk"

.NET 5始めました!

[jp].NET 5がリリースされました。

dotnet.microsoft.com
SDKなど個別にダウンロードしなくても、Visual Studio 2019も16.8.1にアップデートすると、.NET 5を含んだ形の開発環境になります。
そのため、もし、.NET 5を始めるならば、個別ダウンロードよりもVisual Studio 2019の最新化をお勧めします。
これで、.NET Core 2.1 LTS / .NET Core 3.1 LTS / .NET 5の3つから選択ができますね。
そして、WPFで作成するならば、.NET Core 3.1 LTSか、.NET 5でということになります。
.NET 5での変更点で気になるところをピックアップしてみましょう。

C# 9.0

.NET 5では、C# 9.0が使えます。
C# 9.0 の新機能 - C# ガイド | Microsoft Docs

最上位ステートメント

これからは、コンソールに「Hello World!」と表示したいときは、次の1行になります。

System.Console.WriteLine("Hello World!");

**

変数宣言と同時に初期化したいときなど、varが使えないところだったりするとイコールの右と左に同じように型名を書かないといけないですよね。
これからは、左側だけ書けば、右側は「new()」と型名なしで書けるようになります。シンプルです。

private List _observations = new();

これ、左側が省略だったら、var と同じ感覚だったので、個人的な感想としては左側の型名省略だったら更にうれしかったかも。

WPFアプリ作成時の変更点

WPF SDK(Microsoft.NET.Sdk.WindowsDesktop)から、.NET SDK(Microsoft.NET.Sdk) に変更なりました。
変更しないとコンパイル時にワーニング表示されます。
もし、.NET Core 3.1のプロジェクトのターゲットを.NET 5に変えたならば、csprojファイルで

Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"

となっているところを

Project Sdk="Microsoft.NET.Sdk"

にかえておきましょう。

まとめ

.NET 5はいいぞっ!