3

将来の読者のための更新: .NET 4 が登場するとLazyInit<T>、CTP から名前Lazy<T>が変更され、構造体からクラスに変更されるため、変更可能な構造体が問題になる理由の例を除いて、これはほとんど適用されません。気をつけないと。

Parallel Extensions June CTP で LazyInit を試してみましたが、次のコードは同じ Guid を 1000 回出力すると予想していましたが、代わりに 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; }
        }
    }
}
4

1 に答える 1

12

短いバージョン: 静的な非読み取り専用を作成すると、発生しているバグが修正されます。

詳細バージョン: これは、C# の非常に誤解されている部分です。構造体にアクセスすると、構造体のコピーにアクセスしています。LazyInit.Value の基になる呼び出しは変更操作です。通常はコピーバックが実行されますが、読み取り専用フィールドの場合はコピーバックを実行する方法がないため、初期化されていない値が残ります。

非常に詳細な説明: http://ericlippert.com/2008/05/14/mutating-readonly-structs/

于 2008-11-11T02:34:01.283 に答える