Visual studio 在调用之前在调试器中评估函数
Visual studio evaluates func in debugger before it is called
我想实现自定义Lazy<T>
class,只是为了实现它。有趣的是,当我将函数传递给构造函数时,在调试器中我已经可以看到对象已经在函数内部创建,即使实际调用是在 Value
内部。这是因为调试器评估 _func
本身还是我不明白 Func<>
是如何工作的?
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% 确定这是否是我问题的答案。
当您添加断点时,调试器会向您显示当前作用域中存在的变量和属性的值。默认情况下会评估它们,您可以通过几种方式处理此行为:
1) 将 DebuggerBrowsable Never 属性添加到您的 属性,然后它的值将不会显示在本地 window:
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
2) 在 Visual Studio 中禁用此行为:工具 -> 选项 -> 调试 -> 常规 -> 然后禁用 "Enable property evaluation..."
3) Look how Lazy does it。我们看到属性添加到 class:
[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 泛型类型的默认值。
我想实现自定义Lazy<T>
class,只是为了实现它。有趣的是,当我将函数传递给构造函数时,在调试器中我已经可以看到对象已经在函数内部创建,即使实际调用是在 Value
内部。这是因为调试器评估 _func
本身还是我不明白 Func<>
是如何工作的?
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% 确定这是否是我问题的答案。
当您添加断点时,调试器会向您显示当前作用域中存在的变量和属性的值。默认情况下会评估它们,您可以通过几种方式处理此行为:
1) 将 DebuggerBrowsable Never 属性添加到您的 属性,然后它的值将不会显示在本地 window:
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
2) 在 Visual Studio 中禁用此行为:工具 -> 选项 -> 调试 -> 常规 -> 然后禁用 "Enable property evaluation..."
3) Look how Lazy does it。我们看到属性添加到 class:
[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 泛型类型的默认值。