サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
掃除・片付け
ikorin2.hatenablog.jp
筆者の動作確認: Unity 2021.3.29f1 忙しい人向けの結論 [Preserve] internal sealed class MarkerForInternet : UnityWebRequest { } 上記のコードをどこかに書いておけば、UnityWebRequest を使っている判定になり、自動でインターネット権限をつけてくれる。 インターネット権限の付与 Unity で通信したいときは UnityWebRequest を使うと、Android の場合はビルド時に自動的にインターネット権限が付与される。 しかし、C# 標準ライブラリの HttpClient を使うと SocketException: Access denied のような例外が出る。あるいは、IL2CPP を通した場合、出る例外が少し違う。 WebException: Error: NameResolut
.NET framework 4 で追加されたTaskおよび .NET framework 4.5 で追加されたasync, awaitキーワードによって、C# の非同期処理は非常にに簡単になりました。 Windows Form, WPF, UWP, Unity など各種フレームワーク上の場合、非同期処理はスレッドやコールバック処理など面倒なことはほぼ完璧に隠蔽され、難しいことを意識することなく直感的に記述できるようになりました。 しかし、例えば上記のような既存のフレームワークを使わず、独自の GUI フレームワークを作りたいような場合、同期コンテキストについて知っておく必要があります。 (GUIフレームワークを自分で作る人がいるのかという疑問はひとまず置いておいて……) なお、ここでいうフレームワークとは、開発者がその上でアプリケーションを作成することを目的としているような、基盤となるよ
突然ですが、C# で sizeof((byte, int)) の値はいくつでしょう?(64bit 環境) byte が1バイト、int が4バイト、つまり (byte, int) は5バイト……ではないです。 答えは8バイト。アライメント上に乗るようにパディングがあるからですね。 0 1 2 3 4 5 6 7 byte - - - int (0) int (1) int (2) int (3) では、sizeof((byte, int, short)) の値はいくつでしょう?(64bit 環境) byte, int, short がそれぞれ1, 4, 2 バイトで、アライメント上に乗せると4, 4, 4 で12バイト? いいえ、答えは8バイトです。レイアウトは以下のようになります。 0 1 2 3 4 5 6 7 byte - short (0) short(1) int (0) int
WGSL WGSL (WebGPU Shader Language) の文法や仕様の日本語解説が少ないので自分用メモ。仕様を網羅しているわけではなく、自分が書く上で必要そうな部分を適当に抜粋してまとめた。 Tour of WGSL と WGSL の仕様 から日本語に訳して簡単にまとめた。 仕様は長すぎて辛いけど困ったら見るべき。全部書いてある。 定数 (const) const の型は abstract-int と abstract-float として扱われ、精度は実際の変数に代入する場所で決まる。 変数 let はイミュータブルな変数の宣言。ミュータブル変数は var で宣言する。 var は var<AS> で宣言する。AS はアドレス空間 (address spaces) var<function> 関数内のローカル変数のデフォルトは var<function> であり、普通ローカル
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
interface の静的仮想メンバー C# 11 から interface に静的仮想メンバーを持たせられるようになりました。これは別名 "Generic Math" と呼ばれており、数値の演算がジェネリクスを通して呼べるようになりました。 しかし、本記事では interface の静的仮想メンバーがもたらす別の使い方を解説します。 主たる動機である Generic Math の方の解説はググってください、ここでは説明しません。 「interface の静的仮想メンバー」が何かを簡単に言うと、interface に staitc メソッドを定義することで、そのインターフェースを継承した具象型に static メソッドの実装を強制させることができるのです。 public interface IFoo { static abstract void Foo(); } 上記のように interf
明日使えない小ネタ記事です。 C# 10 から文字列補間の $"" 構文が独自拡張可能になっています。 これはパターンベースになっており、特定の条件を満たす型を書くことで動作します。 本記事ではまともな使い方やメリットについては解説しません。 まともな使い方や実装方法は公式ドキュメントを見てください。 これをハックして、文字列補間前の文字列を取得してみます。 以下のような型を作ります。 using System.Runtime.CompilerServices; [InterpolatedStringHandler] public readonly struct NotInterpolation { public string Value { get; } public NotInterpolation( int literalLength, int formattedCount, [Ca
デバッグとリリースで処理を変えたいときは普通は大体以下のように書きます。 public void Foo() { #if DEBUG Console.WriteLine("This is Debug."); #else Console.WriteLine("This is Release"); #endif } 正直見にくいです。コンパイルされない側の記述は Visual Studio のコードアナリティクスもシンタックスハイライトもなくなり、非常に使いにくい。当然、関数名変更などのリファクタリングも効かなくなり、いつの間にかリリースビルドが通らないコードになっていたり、なんてこともあり得ます。 これぐらいの分岐なら全然いいですが、もっといくつもシンボルがあって大量に分岐があちこちに書かれているコードは非常に苦痛。おいおいここはC++じゃないんだぜ なので、以下のように書きます。 inte
小ネタです。 はてなブログの C# の linter が古いのか、シンタックスハイライトがめちゃくちゃになってますが気にしないでください。 string Foo(int? num) { // これはコンパイルエラー return $"The num is {num == null ? "NULL" : num.Value.ToString()}."; } string interpolation ($文字列) の中に三項演算子は書けないです。もしこれを書けるように認めると、コンパイラの構文解析のコストが高くなりすぎるらしいです、たしか。 悲しいですね。 なのでコンパイラの気持ちになってあげましょう。 string Foo(int? num) { // 全体を () で包むとコンパイルが通る return $"The num is {(num == null ? "NULL" : num.V
方法だけ知りたい生き急いでいる人用 // using System.Runtime.CompilerServices; RuntimeHelpers.RunClassConstructor(typeof(Hoge).TypeHandle); 以下説明 static コンストラクタが呼ばれない状況 C# の構造体やクラスには、インスタンスのコンストラクタとは別に、static コンストラクタを書くことができます。 public class Hoge { // インスタンスコンストラクタ public Hoge() { ... } // static コンストラクタ static Hoge() { ... } } 通常、static コンストラクタは、初めてインスタンスコンストラクタが呼ばれた時に最初の1回だけ実行されます。つまり、型に対して静的な初期化処理を書くことができます。 さらに、言語
おことわり ハック記事です。非推奨 API は呼び出すべきではありません。 非推奨属性 (Obsolete) System.ObsoleteAttribute はメソッドやクラスが非推奨であることをマークする属性です。引数の有無によって警告にするかコンパイルエラーにするかを選べます。 メソッドにつければそのメソッドのみ、クラスにつけるとクラス全体が非推奨になります。 // 引数無しは警告 [Obsolete] public void Foo1() { } // メッセージ付き警告 [Obsolete("Use another method because ...")] public void Foo2() { } // 第二引数を true にするとコンパイルエラー [Obsolete("Use another method because ...", true)] public void
この記事は .NET6 Advent Calendar 2021 の14日目の記事です。 .NET6 におけるバッファメモリ確保 以前 .NET Framework4.8 でメモリ確保の方法についてベンチマークを取り、記事にしたことがあります。 (参考 (C#) メモリ確保ベンチマーク 6種盛り) .NET6 でいろいろとバージョンアップしているので、.NET6 でベンチマークを取ってみました。 前回は6通りの方法を試しましたが、今回は新たに追加されたメソッドを含めて7通りを試します。 ベンチマークライブラリはいつも通り BenchmarkDotNet を使用します。 // (1) [Benchmark(Baseline = true, Description = "new byte[]")] public byte[] NewAlloc() { return new byte[Size]
この記事は Qiita C# Advent Calendar 2021 の5日目の記事です。 はじめに C# で async/await が登場してからずいぶんと時間がたち、モダンな C# においてはほぼ必須となりました。Unity でも UniTask などのライブラリもあり、簡単に非同期処理が書けます。この記事では C# での非同期処理の歴史にも触れつつ async/await の動作原理について書きます。 Unity C# の話を書いた方が需要が高そうなので Unity および UniTask を前提にした説明とコードが多く出てきますが、async/await は C# の言語機能であるため、動作原理自体は .NET でも同じです。非 Unity の文脈では適宜読み替えてください。 また、詳細を完璧に説明するよりもわかりやすさを重視したため、一部正確さを欠いた説明をしています。ご了承
構造体の既定のコンストラクタ 構造体 (struct) には既定のコンストラクタが暗黙的に定義されます。 public struct MyStruct { public string? Value { get; } public MyStruct(string? value) { Value = value; } } // 既定のコンストラクタ var myStruct = new MyStruct(); // myStruct.Value == null Console.WriteLine(myStruct.Value); 既定のコンストラクタはすべてのフィールドが0や null で初期化された状態であり、この引数のない既定のコンストラクタを自分で書くことはできませんでした。つまり、C#9.0 以前のコードでは default(T) と同義でした。 ところが、C#10.0 からは構造体に
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
この記事は「C# Advent Calendar 2020」の24日目の記事です。 3種類の定数と分岐削除 C# には3種類の定数があります。とはいえ、実際に C# のソースコードとして目に見えるのは1種類だけでconstとして書くものです。それぞれ順に見ていきましょう。 C#定数 (const) 最も一般的な定数はconstキーワードで定義するものです。 void Hoge() { const int a = 5; if(a == 5) Console.WriteLine("a is 5"); else Console.WriteLine("a is not 5"); } constは C# の静的なソースコードの状態で定数であることを表現します。上の例ではconstは変数として定義されますが実際にはコンパイルすると変数はなくなり、aにリテラルの5が直接埋め込まれます。静的に5であること
System.Span<T> および System.ReadOnlySpan<T>はメモリの連続領域を表すための配列ライクなオブジェクトです。 配列T[]およびそのスライス、スタックメモリstackalloc T[]、ポインタ (マネージドとアンマネージドの両方)を統一的に扱える便利なものです。 これらは .NET Core の時代に後から導入されたもので、これによって得られるパフォーマンス効果を100%使うためにはランタイムに修正が必要でした (Fast Span)。しかし、ランタイムに修正を加える前の古いランタイム (.NET Framework) およびランタイムを指定せず API が一致していれば使えるというライブラリ用の API 仕様である .NET Standard ではこれが使えず、本来のパフォーマンスを得られないが挙動だけ合わせたものとして提供されます (Slow Span
.NET CoreでNugetのパッケージのdllはデフォルトではビルド出力にコピーされないし、 Visual Studio上から設定で出力するように設定変更もできない(たぶん)(何故) [2020/6/29 追記] この記事の内容は.net core 2.x 時代の話で、.net core 3.0 からはdllがデフォルトでビルド出力にコピーされます。 なのでこの記事の内容自体が今は不要です。。。 .csprojファイルに以下の設定を直接書き足す。 <PropertyGroup> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup> はい。 よかったですねぇ~ 参考文献 NuGet を使用したパッケージ管理 - マイクロソフト系技術情報 Wiki
先日VOICEROID +EXを購入したんですが、どうにもインストールが上手くいかなくてつまったのでメモ書き程度に。どこかで同じような症状になっている人の目に留まれば幸いです。 購入したのはダウンロード版ではなくパッケージ版なので、とりあえずディスクを光学ドライブに入れてランチャーソフトを起動します。 後は一番上の大きいインストールボタンを押して、指示に従ってインストールすれば終わり……終わり…… 終わらん 「ライセンス認証ドライバをインストールしています」と出てきたウィンドウのプログレスバーが0%から永遠に動かない。仕方がないのでインストーラーをキャンセルして終了しようとしてもこれまた永遠に終了しない。 仕方がないのでタスクマネージャーからプロセスをキルして無理やり閉じました。どうなってるんだ…… [2020/10/11 追記] 色々な方から、インストール時にブルースクリーンになってしま
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の配列が来るとは限らない点。要求した以上の長さの配列が返って
バッファの確保用にnew byte[N]なんて書いたらモテませんよ。とはいえ正直確保するバイト数次第。ベンチマーク見ましょう。 メモリ確保 6種盛り メモリ確保(+破棄)の方法を6種用意した。 // (1) new byte[] MarshalAlloc() { return new byte[N]; } // (2) ArrayPool void SharedPool() { var array = ArrayPool<byte>.Shared.Rent(N); ArrayPool<byte>.Shared.Return(array); } // (3) Marshal から確保 void MarshalAlloc() { var array = Marshal.AllocHGlobal(N); Marshal.FreeHGlobal(array); } // (4) (3) + Mem
15パズルってご存知ですか? 知ってても知らなくても15パズルの話をするんですが。はい。 あと、本記事は数学的な厳密な証明はせずに感覚的にエイッヤッ~とやっているので正確じゃないです。 でもたぶんあってる。はい。 これ 簡単に言いますと、1マス空いている4×4のマスでセルを移動させながら、 左上から順に数字を並べるパズルです。 アルゴリズムも単純でプログラミング初心者でも割と簡単に実装できるゲームです。 と思っていた時期が私にもありました。 15パズルの欠陥 というのは半分冗談で、ゲームのアルゴリズム自体は別に難しくないです。 問題はこの15パズルというゲームが持つ本質的な欠陥についてです。 端的に言うと、絶対に完成できない形が存在します。 これが完成形です。 そして、次が完成不可能な形の一例です。 このように完成形から1つだけ入れ替えた形は、どれだけパズルをグルグルまわしても 絶対に完成
このページを最初にブックマークしてみませんか?
『ikorin2.hatenablog.jp』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く