并行扩展:帮助我理解LazyInit

时间:2021-09-08 03:10:34

Update for future readers: When .NET 4 comes out, LazyInit<T> from the CTP will have been renamed to Lazy<T> and will be changed from a struct to a class, so very little of this will apply, except as an illustration of why mutable structs can be problematic if you're not careful.

未来读者的更新:当.NET 4发布时,来自CTP的LazyInit 将被重命名为Lazy 并将从一个结构更改为一个类,因此除了作为如果你不小心,为什么可变结构可能会有问题。

I've been experimenting with LazyInit in the Parallel Extensions June CTP, and I would expect the following code to print out the same Guid a thousand times, but instead it prints out a thousand different Guids. Clearly I'm missing something obvious here about how LazyInit is supposed to work, and I'd appreciate if someone would kindly point out what it is.

我一直在使用Parallel Extensions June 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 个解决方案

#1


12  

Short Version: Make the static non-readonly and it will fix the bug you are experiencing.

简短版本:使静态非读取,它将修复您遇到的错误。

Long Version: This is a very misunderstood portion of C#. When you access a struct you are accessing a copy of the struct. The underlying call of LazyInit.Value is a mutating operation. Normally a copyback is performed but in the case of a read-only field there is no way to perform the copy back and hence you are still left with an uninitialized value.

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

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

非常详细的解释:http://ericlippert.com/2008/05/14/mutating-readonly-structs/

#1


12  

Short Version: Make the static non-readonly and it will fix the bug you are experiencing.

简短版本:使静态非读取,它将修复您遇到的错误。

Long Version: This is a very misunderstood portion of C#. When you access a struct you are accessing a copy of the struct. The underlying call of LazyInit.Value is a mutating operation. Normally a copyback is performed but in the case of a read-only field there is no way to perform the copy back and hence you are still left with an uninitialized value.

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

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

非常详细的解释:http://ericlippert.com/2008/05/14/mutating-readonly-structs/