ネコのために鐘は鳴る

寺院に住み着くパソコ〇好き

.NET

(C#) ジェネリック型制約違いのオーバーロード

小ネタです。 C# でジェネリックメソッドには型制約をつけることができます。 この時、C# ではシグネチャ (メソッド名、引数、戻り値など) が同じでジェネリック型制約のみが異なるメソッドはオーバーロードとして書くことができません。 public static void…

(C#) ValueTuple のサイズとレイアウト

突然ですが、C# で sizeof((byte, int)) の値はいくつでしょう?(64bit 環境) byte が1バイト、int が4バイト、つまり (byte, int) は5バイト……ではないです。 答えは8バイト。アライメント上に乗るようにパディングがあるからですね。 0 1 2 3 4 5 6 7 byte…

(C#) オブジェクトの破棄の可否を型で制限する

Dispose による破棄 C# で明示的に破棄が必要なオブジェクトは、一般的に IDisposable インターフェースによって破棄メソッドを提供します。 public sealed class MyObject : IDisposable { public void Dispose() { // 破棄処理 } } ところが C# の Dispose…

(C#) interface の静的仮想メンバーでジェネリックコンストラクタ

interface の静的仮想メンバー C# 11 から interface に静的仮想メンバーを持たせられるようになりました。これは別名 "Generic Math" と呼ばれており、数値の演算がジェネリクスを通して呼べるようになりました。 しかし、本記事では interface の静的仮想…

(C#) 文字列補間されていない文字列補間を取得する

明日使えない小ネタ記事です。 C# 10 から文字列補間の $"" 構文が独自拡張可能になっています。 これはパターンベースになっており、特定の条件を満たす型を書くことで動作します。 本記事ではまともな使い方やメリットについては解説しません。 まともな使…

(C#) Obsolete によるコンパイルエラーを無視する

おことわり ハック記事です。非推奨 API は呼び出すべきではありません。 非推奨属性 (Obsolete) System.ObsoleteAttribute はメソッドやクラスが非推奨であることをマークする属性です。引数の有無によって警告にするかコンパイルエラーにするかを選べます…

(C#) C# 10でも ref field したい

小ネタです。 参照フィールドとは C# 11 から ref field という機能が使えるようになる予定です。(マージはされていますが、本記事執筆時点では正式リリースはされていません) ref 参照を ref 参照のまま ref struct のフィールドとして保持できるものです。…

(C#) LINQPad で JIT のネイティブコンパイル結果を見る

LINQPad について LINQPad は C# 用の簡易実行環境ツールです。簡易といいつつも Nuget Package も参照できるうえ、IDE と遜色ないぐらいのデバッグ機能があります。 むしろ、REPL 的に1行ずつ結果を見ながら追記したり、書き捨てのコードを試し書きするなど…

(C#) ModuleInitializer からのみ呼べるメソッドを作る

小ネタです。C# 9 から ModuleInitializer 属性をつけると、アセンブリのロード時に一度のみ呼び出される処理を書くことができます。 プログラマが処理を差し込めるあらゆるタイミングの中で最も早く、Main メソッドより先に呼び出すことすら可能です。楽し…

(C#) メモリ確保ベンチマーク on .NET6

この記事は .NET6 Advent Calendar 2021 の14日目の記事です。 .NET6 におけるバッファメモリ確保 以前 .NET Framework4.8 でメモリ確保の方法についてベンチマークを取り、記事にしたことがあります。 (参考 (C#) メモリ確保ベンチマーク 6種盛り) .NET6 で…

(C#) async/await を理解する

この記事は Qiita C# Advent Calendar 2021 の5日目の記事です。 はじめに C# で async/await が登場してからずいぶんと時間がたち、モダンな C# においてはほぼ必須となりました。Unity でも UniTask などのライブラリもあり、簡単に非同期処理が書けます。…

(C#) C#10 で構造体の既定のコンストラクタを禁止する

構造体の既定のコンストラクタ 構造体 (struct) には既定のコンストラクタが暗黙的に定義されます。 public struct MyStruct { public string? Value { get; } public MyStruct(string? value) { Value = value; } } // 既定のコンストラクタ var myStruct =…

(C#) 構造体で列挙型ライクな定義を作る

小ネタです。毎回 C# のあまり一般的ではない珍妙な実装の記事ばかり書いていますが、今回もまた珍妙な実装です。実用性は一応ありますが、一般的ではない珍妙な方法だと理解した上でご利用ください。 概要 構造体をつかって列挙型のような型を作っていきま…

(C#) lock フリーで高速なスレッドセーフ操作

C# で排他制御をしたい場合いくつか方法があります。何も考えずに雑にlock構文を書くだけで同期は取れるのですが、より高度にパフォーマンスチューニングしたい場合のため、効率的な方法を紹介します。 例えば以下のようなものがあるとします。 // スレッド…

(C#) 小ネタ $ 文字列中の三項演算子

小ネタです。 はてなブログの C# の linter が古いのか、シンタックスハイライトがめちゃくちゃになってますが気にしないでください。 string Foo(int? num) { // これはコンパイルエラー return $"The num is {num == null ? "NULL" : num.Value.ToString()…

(C#) interface/core パターンによるポリモーフィズム

継承の濫用による設計の矛盾 コード共通化のためだけの継承の濫用が設計の矛盾を生むというのを分かっている方は、下の問題設定だけ見て、次の項まで読み飛ばしてください。 問題設定 人間・犬・猫には「歩く」という共通の振る舞いがあり、現在の「位置」を…

(C#) Source Generator で typeof の型名を取得する

C# 9.0 から使える Source Generator、良いですね。アプリケーションを作る側の人が Source Generator を作ることは少ないと思いますが、ライブラリを作る側の人には便利ですよね。 基本的な使い方・作り方はここでは解説しません。公式の説明や公式サンプル…

(C#) 型の外部から疑似的に interface を追加する

interface を後付けしたい interface は C# でポリモーフィズムを実現するために、メソッド・プロパティの宣言だけを決めておき、実際の挙動は型の実装者に任せるというものです。今更説明するまでもないですね、普段みなさんが使ってるやつです。 普通は型…

(C#) 3種類の定数と JIT コンパイル時最適化

この記事は「C# Advent Calendar 2020」の24日目の記事です。 3種類の定数と分岐削除 C# には3種類の定数があります。とはいえ、実際に C# のソースコードとして目に見えるのは1種類だけでconstとして書くものです。それぞれ順に見ていきましょう。 C#定数 (…

(C#) Fast Span と Slow Span の挙動の不一致の罠

System.Span<T> および System.ReadOnlySpan<T>はメモリの連続領域を表すための配列ライクなオブジェクトです。 配列T[]およびそのスライス、スタックメモリstackalloc T[]、ポインタ (マネージドとアンマネージドの両方)を統一的に扱える便利なものです。 これら</t></t>…

(C#) ランタイムが Blazor WebAssembly か否かを取得する

実行中のOS が何であるかを取得する時はSystem.Environment.OSVersion.Platformを使えそうかと思ってました。 using System; // Windows 10 なら "Win32NT" Console.WriteLine(Environment.OSVersion.Platform); ところが、これを Mac の .NET Core で取得す…

(C#) エンディアン固定でシリアライズ

今回のオチ System.Buffers.Binary.BinaryPrimitives クラスを使いましょう エンディアンを固定でシリアライズしたい longの値をbyte[]にしたい時、普通はSystem.BitConverter.GetBytes(long)で困らないんですが、BitConverterのエンディアンは固定じゃない…

(C#) static コンストラクタを手動で呼ぶ

方法だけ知りたい生き急いでいる人用 // using System.Runtime.CompilerServices; RuntimeHelpers.RunClassConstructor(typeof(Hoge).TypeHandle); 以下説明 static コンストラクタが呼ばれない状況 C# の構造体やクラスには、インスタンスのコンストラクタ…

(C#) ArrayPool<T>.Shared 解体新書

ArrayPool<T>.Shared みなさんはSystem.Buffers.ArrayPool<T>.Shared使ってますか?使ってない?なら使いましょう。 ArrayPool<T>.Sharedは短期間だけ利用するようなバッファを貸してくれるものです。 new T[N]と違い、一度使った配列を使いまわすことができるのでガ</t></t></t>…

(C#) #if DEBUG を使わないデバッグ分岐

デバッグとリリースで処理を変えたいときは普通は大体以下のように書きます。 public void Foo() { #if DEBUG Console.WriteLine("This is Debug."); #else Console.WriteLine("This is Release"); #endif } 正直見にくいです。コンパイルされない側の記述は…

(C#) メモリ確保ベンチマーク 6種盛り

バッファの確保用にnew byte[N]なんて書いたらモテませんよ。とはいえ正直確保するバイト数次第。ベンチマーク見ましょう。 メモリ確保 6種盛り メモリ確保(+破棄)の方法を6種用意した。 // (1) new byte[] MarshalAlloc() { return new byte[N]; } // (2) A…

(C#) Span<T> を List<T>.AddRange したい

タイトル通りですが本記事執筆時点 (2020/4/15) の最新である .NET Core 3.1 ではList<T>のAddRangeメソッドにダイレクトにSpan<T>およびReadOnlySpan<T>を突っ込むことはできません。というのもList<T>のAddRangeメソッドは public void AddRange(IEnumerable<T> items); </t></t></t></t></t>…

(C#) List<T>からSpan<T>を引き抜いて高速化

List<T>はGetEnumerator()を実装しているため当然foreachで回せる。foreachの速度を落とさないために具象型のEnumeratorを返したりEnumeratorを構造体実装していたりと工夫は凝らされているが、それでもSpan<T>やT[]には数倍~10倍程度遅い。この点に関しては、List<T></t></t></t>…

(C#) ラムダ式による this のキャプチャ

ラムダ式による外部変数のキャプチャは、コンパイラによって暗黙的に匿名クラスが作られ、コールされるたびに匿名クラスのインスタンスがnewされるため、ヒープアロケーションが発生する。 using System; public class Class { public Action Method(int num…

(C# 雑記) Linq の Count() と IReadOnlyCollection<T>

Linq のCount()、つまりint Enumerable.Count(IEnumerable<T>)は原理的には全列挙による数え上げだが、配列ライクなものは初めから要素数を持っているのでO(N)を回す必要はない。そのため、配列ライクなものについては直接要素数を取るよう最適化が施されている</t>…