最近,我的同事向我展示了一段无法正常工作的代码:
public class SomeClass
{
private IList<Category> _categories;
public void SetCategories()
{
_categories = GetCategories() ?? new List<Category>();
DoSomethingElse();
}
public IList<Category> GetCategories()
{
return RetrieveCategories().Select(Something).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
(我知道运算符是多余的,因为linq ToList将始终返回一个列表,但这就是代码的设置方式).
问题是_categories为null.在调试器中,设置断点_categories = GetCategories() ?? new List<Category>(),然后单步执行DoSomethingElse(),_ categories仍然为null.
直接将_categories设置为GetCategories()工作正常.拆分?在一个完整的if语句工作正常.空合并运算符没有.
它是一个ASP.NET应用程序,所以一个不同的线程可能会干扰,但它在他的机器上,只有他在浏览器中连接._cateogories不是静态的,或任何东西.
我想知道的是,这怎么可能发生?
编辑:
只是为了增加奇异性,除了初始化类_categories之外,永远不会设置除该功能之外的任何地方.
确切的代码是这样的:
public class CategoryListControl
{
private ICategoryRepository _repo;
private IList<Category> _categories;
public override string Render(/* args */)
{
_repo = ServiceLocator.Get<ICategoryRepository>();
Category category = _repo.FindByUrl(url);
_categories = _repo.GetChildren(category) ?? new List<Category>();
Render(/* Some other rendering stuff */);
}
}
public class CategoryRepository : ICategoryRepository
{
private static IList<Category> _categories;
public IList<Category> GetChildren(Category parent)
{
return _categories.Where(c => c.Parent == parent).ToList<Category>();
}
}
Run Code Online (Sandbox Code Playgroud)
即使它GetChildren神奇地返回null,CategoryListControl._categories仍然永远不应该为null.由于IEnumerable.ToList(),GetChildren也永远不会返回null.
编辑2:
尝试@ smartcaveman的代码,我发现了这个:
Category category = _repo.FindByUrl(url);
_categories = _repo.GetChildren(category) ?? new List<Category>();
_skins = skin; // When the debugger is here, _categories is null
Renderer.Render(output, _skins.Content, WriteContent); // When the debugger is here, _categories is fine.
Run Code Online (Sandbox Code Playgroud)
同样,在测试时if(_categories == null) throw new Exception(),_categories在if语句中为null,然后没有抛出踩过异常.
所以,似乎这是一个调试器错误.