2017-10-16 107 views
0

我想实现自定义Lazy<T>类,只是为了实现它。有趣的是,当我将函数传递给构造函数时,在调试器中,我已经可以看到该对象是在函数内创建的,即使实际调用在Value之内。这是因为调试器自己评估_func还是我不明白Func<>的工作原理?Visual Studio在调试器中调用函数之前调用函数

class Program 
{ 
    static void Main(string[] args) 
    { 
     var lazyObj = new LazyTest<Entity>(() => new Entity { Foo = 5 }); // Debugger shows that Entity is already created here and Foo = 5. 
     var entity = lazyObj.Value; // Creation of Entity should happen here. 
     Console.WriteLine(entity.Foo); 

     Console.Read(); 
    } 
} 

public class Entity 
{ 
    public int Foo { get; set; } 
} 

public class LazyTest<T> 
{ 
    private T _value; 
    public T Value 
    { 
     get 
     { 
      if (_value == null) 
       _value = _func(); 
      return _value; 
     } 
    } 
    private Func<T> _func { get; set; } 

    public LazyTest(Func<T> func) 
    { 
     _func = func; 
    } 

我发现Lazy<T>内部使用性质internal T ValueForDebugDisplay,但我不是100%肯定,如果这是一个回答我的问题。

回答

2

添加断点时,调试器会显示当前范围中存在的变量和属性的值。这是在默认情况下评估它们,你可以在一对夫妇的方式处理这个问题:

1)添加DebuggerBrowsable决不归因于你的财产,那么它的价值是不会在局部变量窗口中显示:

[DebuggerBrowsable(DebuggerBrowsableState.Never)

2)禁用此行为在Visual Studio:工具 - >选项 - >调试 - >常规 - >有禁用“启用财产评价...

3)Look how Lazy does it。我们看到的属性添加到类:

[DebuggerDisplay("ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay}")] 
public class Lazy<T> 

你提到的财产,ValueForDebugDisplay,在这里实现:

internal T ValueForDebugDisplay 
{ 
    get 
    { 
     if (!IsValueCreated) 
     { 
      return default(T); 
     } 
     return ((Boxed)m_boxed).m_value; 
    } 
} 

正如你所看到的,它的价值还没有被创建,它显示了Lazy泛型类型的默认值。

+0

但我的当前实现是否实际创建对象,或者调试器是否为了显示它而创建它?内存什么时候分配给对象?在调用'Value'之前或之后? – FCin

+0

调试器正在创建它以在本地窗口中显示给你。它发生在调试器遇到断点时,我添加了一些方法来解决上述问题,祝你好运:) –

+0

其实,你是对的。我插入了一个'Console.WriteLine',看它什么时候打印出来,当我调用'Value'或者我在调试器中查看'Value'的时候,它会打印出来。 – FCin

相关问题