代码之家  ›  专栏  ›  技术社区  ›  Joel Mueller

并行扩展:帮助我理解LazyInit<T>

  •  3
  • Joel Mueller  · 技术社区  · 17 年前

    为未来读者更新: LazyInit<T> 从CTP将重命名为 Lazy<T> 并且将从一个结构更改为一个类,所以这几乎不适用,除非作为一个说明,说明如果不小心的话,可变结构可能会有问题。

    我在6月的并行扩展CTP中试用了LazyInit,我希望下面的代码可以打印出一千次相同的Guid,但它可以打印出一千个不同的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; }
            }
        }
    }
    
    1 回复  |  直到 16 年前
        1
  •  12
  •   Eric Lippert    12 年前

    短版本:将静态设置为非只读,它将修复您遇到的错误。

    长版本:这是C#的一个非常被误解的部分。访问结构时,您正在访问该结构的副本。Value的底层调用是一个变异操作。通常会执行回写,但如果是只读字段,则无法执行回写,因此仍保留未初始化的值。

    http://ericlippert.com/2008/05/14/mutating-readonly-structs/