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.Substring()を使う

  • 今のC#は インデクサに範囲指定して抜き出せる
var s = "abcdef";
var s1 = s.Substring(0, 4); //abcd
var s2 = s[0..4]; //abcd

https://qiita.com/YouKnow/items/93b4b978ecb113616fae

  • 更に、Span<T>化するとより高速化される
    • 特に何度も抜き出す処理を行う場合
var s3 = s.AsSpan(0, 4).ToString(); 
var s4 = s.AsSpan()[0..4].ToString();
  • 戻り値はstringではなくReadOnlySpan<char>なのに注意
いぬいぬいぬいぬ

パフォーマンス計測にSystem.Diagnostics.Stopwatchを使う

代わりにBenchmark.NETを使う。

https://github.com/dotnet/BenchmarkDotNet

  • Stopwatch

    • ミリ秒まで
    • 繰り返し処理など全部自分で書く必要がある
    • 処理速度しか記録してくれない
  • Benchmark.NET

    • 簡単に書ける
    • 平均、標準誤差、標準偏差、アロケーションなどを出してくれる
    • パフォーマンス比較で標準的に使われている
  • 例外

    • Benchmark.NETを導入できない場合
いぬいぬいぬいぬ

namespaceブロック

  • 今のnamespaceはブロックじゃなくて1行で書ける
    • 全コードのインデントが一つ減る! これはでかい!
namespace Example;

「やたらインデントが多いC#」は過去のもの。

  • 例外
    • 1ファイル内でたくさん名前空間を制限したい時
      • そんなことある?
    • 名前空間の入れ子をやりたい時
      • でも namespace A.B.C; って書けるしなぁ… いる?
いぬいぬいぬいぬ

nullの判定に==を使う (obj == 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重の意味で怪しいと思うべき