2008-11-11 3 views
3

Mise à jour pour les futurs lecteurs: Lorsque .NET 4 sort, LazyInit<T> du CTP auront été renommés Lazy<T> et seront changés d'un struct à une classe, donc très peu de cela s'appliquera, sauf pour illustrer pourquoi les structures mutables peuvent être problématiques si vous ne faites pas attention.extensions parallèles: Help Me Understand LazyInit <T>

J'ai expérimenté avec LazyInit dans le CTP June de Parallel Extensions, et je m'attendrais à ce que le code suivant imprime le même Guid un millier de fois, mais à la place il imprime un millier de Guids différents. Manifestement, il me manque quelque chose d'évident ici sur la façon dont LazyInit est censé fonctionner, et j'apprécierais que quelqu'un veuille bien préciser ce que c'est.

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; } 
     } 
    } 
} 

Répondre

12

Version courte: Rendre la statique non-readonly et corriger le bug que vous rencontrez.

Version longue: Il s'agit d'une portion de C# très mal comprise. Lorsque vous accédez à une structure, vous accédez à une copie de la structure. L'appel sous-jacent de LazyInit.Value est une opération de mutation. Normalement, une copie est effectuée, mais dans le cas d'un champ en lecture seule, il n'y a aucun moyen d'effectuer la copie en arrière et donc il vous reste une valeur non initialisée.

explication extrêmement détaillée: http://ericlippert.com/2008/05/14/mutating-readonly-structs/

+0

Merci, je suis revenu à répondre à ma propre question avec le même URL, mais vous me devança! –