最近我的同事给我展示了一段代码,但它并没有正常工作:
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();
}
}
(我知道这个操作符是多余的,因为linq ToList将始终返回一个列表,但这就是代码的设置方式)。
问题在于_categories为空。在调试器中,在_categories = GetCategories() ?? new List<Category>()
上设置断点,然后跳到DoSomethingElse()时,_categories仍将为空。
直接将_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>();
}
}
即使GetChildren返回null,CategoryListControl._categories也绝对不应该为null。GetChildren也永远不应该因为IEnumerable.ToList()返回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.
同时,当测试if(_categories == null) throw new Exception()
时,如果在if语句中_categories为空,那么跳过异常不会被抛出。
所以,看起来这是一个调试器的bug。
GetCategories()
无论如何都不能返回null
。因此,合并运算符也没有用处。 - Pieter van Ginkel