サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
猫
ikorin2.hatenablog.jp
Dispose による破棄 C# で明示的に破棄が必要なオブジェクトは、一般的に IDisposable インターフェースによって破棄メソッドを提供します。 public sealed class MyObject : IDisposable { public void Dispose() { // 破棄処理 } } ところが C# の Dispose パターンには欠点があり、誰が破棄を呼ぶかの責任の所在を明確にできないのです。 もっとも有名なのは Stream ですね。 public void UseStream(Stream stream) { // stream を使う var buffer = new byte[10]; stream.Read(buffer.AsSpan()); // ここで Dispose してもいい? // 呼び出し元でまだ stream を使うから Disp
この記事は Qiita C# Advent Calendar 2021 の5日目の記事です。 はじめに C# で async/await が登場してからずいぶんと時間がたち、モダンな C# においてはほぼ必須となりました。Unity でも UniTask などのライブラリもあり、簡単に非同期処理が書けます。この記事では C# での非同期処理の歴史にも触れつつ async/await の動作原理について書きます。 Unity C# の話を書いた方が需要が高そうなので Unity および UniTask を前提にした説明とコードが多く出てきますが、async/await は C# の言語機能であるため、動作原理自体は .NET でも同じです。非 Unity の文脈では適宜読み替えてください。 また、詳細を完璧に説明するよりもわかりやすさを重視したため、一部正確さを欠いた説明をしています。ご了承
C# で排他制御をしたい場合いくつか方法があります。何も考えずに雑にlock構文を書くだけで同期は取れるのですが、より高度にパフォーマンスチューニングしたい場合のため、効率的な方法を紹介します。 例えば以下のようなものがあるとします。 // スレッドセーフではないもの public static class Foo { private static int[] _array = new int[10]; private static int _updateCount; public static void SetValue(int index, int value) { _array[index] = value; _updateCount++; } public static (int value, int updateCount) GetValue(int index) { retur
継承の濫用による設計の矛盾 コード共通化のためだけの継承の濫用が設計の矛盾を生むというのを分かっている方は、下の問題設定だけ見て、次の項まで読み飛ばしてください。 問題設定 人間・犬・猫には「歩く」という共通の振る舞いがあり、現在の「位置」を持っている。 全ての生き物はデフォルトでは速度1で歩くが、犬と猫は速度2で歩く。 猫は昼寝をし、昼寝を始めると歩かない。 C#er 的には自然な考えとして、まずは継承で実装してみましょう。 public abstract class Walkable { public int X { get; protected set; } public virtual void Walk() => X += 1; } public class Human : Walkable{ } public class Dog : Walkable { public over
interface を後付けしたい interface は C# でポリモーフィズムを実現するために、メソッド・プロパティの宣言だけを決めておき、実際の挙動は型の実装者に任せるというものです。今更説明するまでもないですね、普段みなさんが使ってるやつです。 普通は型定義の段階で interface を継承させて使うのですが、例えば外部ライブラリで定義されている型に自作の interface を継承させることはできません。 public class Apple // 外部ライブラリのクラス { public string Name => "apple"; } public class Orange // 外部ライブラリのクラス { public string Name => "orange"; } public interface IName // 自作の interface { string
List<T>はGetEnumerator()を実装しているため当然foreachで回せる。foreachの速度を落とさないために具象型のEnumeratorを返したりEnumeratorを構造体実装していたりと工夫は凝らされているが、それでもSpan<T>やT[]には数倍~10倍程度遅い。この点に関しては、List<T>は状態をバージョン管理しており、列挙中の変更を検知しているためどうしようもない。forで回したところで、ランタイムによってインデックスの境界値チェックが消える特殊最適化がかかるSpan<T>やT[]には原理的に勝てない。 しかし、List<T>は柔軟で使いやすい。ただ列挙速度も落としたくない。そこで列挙時だけList<T>をSpan<T>にしてしまおうという話。 以下List<T>の実装を簡略化したもの。 public class List<T> { private T[
ArrayPool<T>.Shared みなさんはSystem.Buffers.ArrayPool<T>.Shared使ってますか?使ってない?なら使いましょう。 ArrayPool<T>.Sharedは短期間だけ利用するようなバッファを貸してくれるものです。 new T[N]と違い、一度使った配列を使いまわすことができるのでガベージにならず、メモリ効率がよいです。 // Length = 20 以上のバッファを取得 byte[] array = ArrayPool<byte>.Shared.Rent(20); // 借りたバッファを返す ArrayPool<byte>.Shared.Return(array); ArrayPool<T>のミソは、長さ20を要求した時に20以上の長さの配列が返ってくるのは保証されてますが、長さ20の配列が来るとは限らない点。要求した以上の長さの配列が返って
このページを最初にブックマークしてみませんか?
『ikorin2.hatenablog.jp』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く