並列拡張機能:LazyInit< T>の理解に役立つ
-
07-07-2019 - |
質問
将来の読者向けの更新: .NET 4がリリースされると、CTPの LazyInit< T>
は Lazy< T> に名前が変更されます。 code>を構造体からクラスに変更します。したがって、注意しないと可変構造体が問題になる可能性がある理由の説明を除いて、これはほとんど適用されません。
Parallel Extensions June CTPでLazyInitを試してみましたが、次のコードが同じGuidを1,000回出力すると予想しますが、代わりに1000個の異なるGuidを出力します。明らかに、LazyInitがどのように機能するかについて、ここで明らかな何かを見逃しています。誰かが親切にそれを指摘してくれれば幸いです。
using System;
using System.Diagnostics;
using System.Threading;
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
for (int i=0; i < 1000; i++)
{
Console.WriteLine(TestClass.Instance.Id);
}
Console.Write("Press any key to continue:");
Console.ReadKey();
}
private class TestClass
{
private static readonly LazyInit<TestClass> _instance = new LazyInit<TestClass>(() => new TestClass(), LazyInitMode.EnsureSingleExecution);
public static TestClass Instance
{
get { return _instance.Value; }
}
private TestClass()
{
Debug.WriteLine("TestClass Constructor");
Id = Guid.NewGuid();
}
public Guid Id { get; private set; }
}
}
}
解決
Short Version:静的な非読み取り専用を作成すると、発生しているバグが修正されます。
ロングバージョン:これはC#の非常に誤解されている部分です。構造体にアクセスすると、構造体のコピーにアクセスしています。 LazyInit.Valueの基になる呼び出しは、変化する操作です。通常、コピーバックは実行されますが、読み取り専用フィールドの場合、コピーバックを実行する方法がないため、初期化されていない値が残っています。
非常に詳細な説明: http://ericlippert.com/2008/ 05/14 / mutating-readonly-structs /
所属していません StackOverflow