Open10
C# (もう)やめたほうがいい事メモ
ピン留めされたアイテム
はじめに
- C#は互換性を強く意識した言語・処理系
- なので20年前のコードもコピペでそのまま動く
- 互換性高いことによる問題がある
- 知識がアップデートされない
- 古い書き方をずっとやり続ける
- 新しい記法はパフォーマンスも良くなるように設計されてることが多い
参考
csc.exe
を直接たたく
-
今はコマンドラインは dotnet cli を使う
- コンパイラを直接叩くことはもうしない
-
そもそも今のC#はマルチプラットフォームなのでWindows限定csc.exe指定は良くない
-
例外
- コンパイラを直接制御するツールとかを作るとき(ただし、Windows限定になる)
- Winodows環境でSDKを入れられない環境でC#を使いたいとき
".NET Framework"という用語を使う
.NETのSDK/Runtimeは無印の「.NET」が最新。
2023-07-31時点は.NET 7が最新。
流れ:
- 元々公式実装の「.NET Framework」、第3者実装の「mono」があった。
- mono開発のXamarin社をMSが買収、新しいOSSの「.NET Core」が生まれた
- 乱立していたのでver.5から「.NET」に統一された(中身は.NET Coreの進化系)
- そのため、まだサポートされているが「.NET Framework」や「mono」は古いSDK/Runtimeになる
- .NETのSDK/Runtimeは「.NET」と書くのが現時点では正しい
- 「.NET Framework」や「.NET Core」の用語を使っているのは 古い記事の目印
不要なおまじないを書く
- 今のC#(最新はC#11)は1行Hello world
Console.WriteLine("Hello World");
- 次のおまじないは省略できる
using
namespace
class
-
Main
関数
- 1ファイルで済むスクリプト的な運用ができる
- もちろん、規模が大きい場合は省略しないほうがよい
string.Format()
を使う
- 今のC#は 補完文字列(interpolated string) を使う
var h = "hello";
var w = "world";
var msg = $"{h}, {w}";
- .NET 6以降、コンパイル結果が高速化されている
- 実用面、速度面の両面で今のC#で
string.Format()
を使うメリットがない
- 実用面、速度面の両面で今のC#で
- 例外
- C/C++のコードを機械的に移植する時に使うかも?
String.Substring()
を使う
- 今のC#は インデクサに範囲指定して抜き出せる
var s = "abcdef";
var s1 = s.Substring(0, 4); //abcd
var s2 = s[0..4]; //abcd
- 更に、
Span<T>
化するとより高速化される- 特に何度も抜き出す処理を行う場合
var s3 = s.AsSpan(0, 4).ToString();
var s4 = s.AsSpan()[0..4].ToString();
- 戻り値は
string
ではなくReadOnlySpan<char>
なのに注意
System.Diagnostics.Stopwatch
を使う
パフォーマンス計測に代わりにBenchmark.NETを使う。
-
Stopwatch
- ミリ秒まで
- 繰り返し処理など全部自分で書く必要がある
- 処理速度しか記録してくれない
-
Benchmark.NET
- 簡単に書ける
- 平均、標準誤差、標準偏差、アロケーションなどを出してくれる
- パフォーマンス比較で標準的に使われている
-
例外
- Benchmark.NETを導入できない場合
namespace
ブロック
- 今の
namespace
はブロックじゃなくて1行で書ける- 全コードのインデントが一つ減る! これはでかい!
namespace Example;
「やたらインデントが多いC#」は過去のもの。
- 例外
- 1ファイル内でたくさん名前空間を制限したい時
- そんなことある?
- 名前空間の入れ子をやりたい時
- でも
namespace A.B.C;
って書けるしなぁ… いる?
- でも
- 1ファイル内でたくさん名前空間を制限したい時
==
を使う (obj == null
)
nullの判定に
is
演算子やis not
演算子を使う
if(obj is null){
//...
}
- 比較(
==
)のはずなのに代入(=
)してた…っていうミスを防げる- もちろん色々他のエラーや警告で気が付けるけど
- 演算子オーバーロードされてても判定できる
?.
や??
や??=
を使う
nullチェックの時はvar result = obj ?? new Something();
//古い書き方
Something result;
if(obj == null){
result = new Something();
}
-
nullチェック自体が簡単に書けるのでコードの見通しが良くなる
-
if(obj == null)
が出てきたら2重の意味で怪しいと思うべき
@"..."
逐語的文字列リテラルを使う - 生文字列リテラルを使う