C#空合并运算符返回null最近,同事给我看了一个无效的代码块:publicclassSomeClass{privateIList_categories;publicvoidSetCategories(){_categories=GetCategories()??新列表();DoSomethingElse();}publicIListGetCategories(){returnRetrieveCategories().Select(Something).ToList();(我知道运算符是多余的,因为linqToList将始终返回一个列表,但这就是代码的设置方式)。问题是_categories为空。在调试器中,在_categories=GetCategories()??newList()_categories=GetCategories()??newList()_categories=GetCategories()??newList()上设置断点,然后踩DoSomethingElse(),_categories是仍然为空。将_categories直接设置为GetCategories()效果很好。分裂?在完整的if语句中工作正常。空合并运算符没有。这是一个ASP.NET应用程序,因此不同的线程可能会干扰,但它在他的机器上,只有他在浏览器中连接。_cateogories不是静态的,也不是任何东西。我想知道的是,这怎么会发生?编辑:只是为了增加奇点,除了初始化类之外,从未在任何地方设置_categories。确切的代码是这样的:publicclassCategoryListControl{privateICategoryRepository_repo;私人IList_categories;publicoverridestringRender(/*args*/){_repo=ServiceLocator.Get();类别类别=_repo.FindByUrl(url);_categories=_repo.GetChildren(类别)??新列表();Render(/*一些其他的渲染内容*/);}}publicclassCategoryRepository:ICategoryRepository{privatestaticIList_categories;publicIListGetChildren(Categoryparent){return_categories.Where(c=>c.Parent==parent).ToList();即使GetChildren神奇地返回null,CategoryListControl._categories也不应为null。由于IEnumerable.ToList(),GetChildren也永远不会返回null。编辑2:尝试@smartcaveman的代码,我发现了这个:Categorycategory=_repo.FindByUrl(url);_categories=_repo.GetChildren(类别)??新列表();_skins=皮肤;//当调试器在这里时,_categories为nullRenderer.Render(output,_skins.Content,WriteContent);//当调试器在这里时,_categories就可以了。同样,在测试if(_categories==null)thrownewException()时,if语句中_categories为null,则不会抛出skip异常。所以,它似乎是一个调试器错误。这可能是调试器的问题,而不是代码的问题。尝试打印出该值或使用coalesce运算符在语句后执行空检查。空合并运算符不会被破坏。我一直以类似的方式使用它。还有其他事情正在发生。如果您确定是因为线程问题,请使用lock关键字。我相信这应该有效。公共类SomeClass{私人IList_categories;publicvoidSetCategories(){lock(this){_categories=GetCategories()??新列表();DoSomethingElse();}}publicIListGetCategories(){returnRetrieveCategories().Select(Something).ToList();尝试做一个干净的构建。Buildmenu->Clean,然后再debug。代码本身没问题。(1)DoSomethingElse()可能会在错误发生前将_categories字段设置为null。对此进行测试的一种方法是将_categories字段设置为只读。如果这是错误的,那么您将得到一个编译器错误,即只读字段不能用作赋值目标。(2)您的_categories字段由其他线程中的其他函数设置。无论哪种方式,以下内容都应该可以解决您的问题,或者至少弄清楚它在哪里。公共类SomeClass{privatestaticreadonlyobjectCategoryListLock=newobject();privatereadonlyList_categories=newList();私人布尔_loaded=假;publicvoidSetCategories(){if(!_loaded){lock(CategoryListLock){if(!_loaded){_categories.AddRange(GetCategories());_loaded=真;}}}DoSomethingElse();}publicIListGetCategories(){returnRetrieveCategories().Select(Something).ToList();}}**请参阅编辑后,您似乎有两个不同的字段,它们是IList_categories。CategoryListControl中的_categories字段为null没有意义,但CategoryRepository类中的静态_categories看起来应该根据您发布的内容为null。也许您对哪个字段引发错误感到困惑。我知道该行是在CategoryListControl中调用的,所以您的错误会说它在CategoryListControl类中,但实际的异常可能来自GetChildren()方法,该方法试图从空列表创建子列表)。由于字段名称相同,因此很容易混淆它们。通过将CategoryRepository的_categories字段设置为只读初始化字段来对此进行测试。尽管CategoryRepository中的_categories字段并不总是空的,它可能会受到任何线程问题的影响我解释了如何修复Control类**它是为了确保您正在调试正确的_categories字段,试试这个。_categories=GetCategories()??新列表();if(_categories==null){thrownewException("WTF???");}DoSomethingElse();如果你没有得到“WTF???”exceptionthen你知道错误的根源在别处。并且,关于Linq扩展:Where()和ToList()都不能返回null。如果任何参数为null,这两种方法都将抛出ArgumentNullException。我用反射器检查了这个。请让我们知道您的结果。我现在也很好奇。这可能是因为您启用了优化-在这种情况下,只要编译器可以证明这样做不会改变结果,分配就可能会延迟。当然,这在调试器中看起来很奇怪,但它非常好。以上就是C#学习教程:C#null合并运算符返回null全部内容分享。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。涉及侵权,请点击维权联系管理员删除。如需转载请注明出处:
