??? public class MyClass { public readonly Counter Counter; public void Increment() => Counter.Increment(); public void Show() => Counter.Show(); } public struct Counter { int count; public void Increment() => count++; public void Show() => Console.WriteLine(count); } 出力は?
0 public class MyClass { public readonly Counter Counter; public void Increment() => Counter.Increment(); public void Show() => Counter.Show(); } public struct Counter { int count; public void Increment() => count++; public void Show() => Console.WriteLine(count); } 「0」!mutableな挙動をしてくれない! readonly fieldにするとメモリ領域がロックされて書き換わらなくなってしまう mutable structを使うときは必ず非readonlyにすること 残念ながらコンパイルは通るし特に警告も出ないので注意するしかない
{ var c = Counter; c.Increment(); } public void Show() => Counter.Show(); } mutable structの注意点2 ローカル変数に代入するとそこでコピーされるの でフィールドの値は書き換わらない public class MyClass { public Counter Counter; public void Increment() { ref var c = ref Counter; c.Increment(); } public void Show() => Counter.Show(); } 基本は必ずフィールドを直接触って絶対に代入しないことだが、どうしても 変数に持ちたかったり、他のメソッドに渡す必要がある場合はrefで渡す
オレオレValueStopwatchもいらない 開始地点のlongをGetTimstampで取得して保持するだけ Stopwatch.GetTimestampは昔からあるけれど、2点のtimestampから TimeSpanを取得するGetElapsedTimeは.NET 7から……! 日付の取得 is not FREE ただのlongなので、普通に取り回しがいいです
object gate; T?[]? values = null; public void Add(T item, out int removeKey) { lock (gate) { var index = FindNullIndex(values); values[index] = item; if (lastIndex < index) { Volatile.Write(ref lastIndex, index); } removeKey = index; // index is remove key. } } } public struct FreeListCore<T> where T : class { public void Remove(int index) { lock (gate) { if (values == null) return; if (index < values.Length) { ref var v = ref values[index]; if (v == null) throw new KeyNotF v = null; } } } } Addではnullの場所を検索してそのindexに追加 する、削除キーとしてindexも返す Removeはnull埋め (説明のためコード上省略してますが)リサ イズは拡大のみ(なのでindexがズレない)