关于c#null传播+ null合并运算符的非常奇怪的beahviour

时间:2017-06-20 22:03:11

标签: c#

考虑以下代码:

//get a list that might be null, empty or valid
 var myItems = _myRepo.GetForId(someId);

 if (!myItems?.Any() ?? true)
 {
     throw new Exception();
 }
 //valid list

这段代码在开头可能有点令人困惑,但很好地处理(=短)空列表或空引用。

我甚至写了一个简短的单元测试,以确保我不会在这里欺骗自己。它通过了:

[TestMethod]
public void SomeOtherTest()
{
    //interace that is implemented by _myRepo from code above
    var myRepo = Mock.Create<IMyRepo>();
    myRepo.Arrange(ar => ar.GetForId(Arg.AnyGuid)).Returns(() => null);

    var myItems = myRepo.GetForId(Guid.Empty);

    if (!myItems?.Any() ?? true)
    {
    }
    else
    {
        Assert.Fail();
    }

    myRepo = Mock.Create<ImyRepo>();

    myRepo.Arrange(ar => ar.GetForId(Arg.AnyGuid)).Returns(() => new List<MyItem>());

    myItems = myRepo.GetForId(Guid.Empty);

    if (!myItems?.Any() ?? true)
    {
    }
    else
    {
        Assert.Fail();
    }

    myRepo = Mock.Create<ImyRepo>();

    myRepo.Arrange(ar => ar.GetForId(Arg.AnyGuid)).Returns(() => new List<MyItem> {new MyItem()});

    myItems = myRepo.GetForId(Guid.Empty);

    if (!myItems?.Any() ?? true)
    {
        Assert.Fail();
    }
    else
    {      
    }
}

然后发生了一些非常奇怪的事情:

在另一个(我的实际)单元测试中,我设置如下:

 myRepo.Arrange(ar => ar.GetForId(Arg.AnyGuid)).Returns(() => new List<MyItem> {new MyItem()});

这与我在传递单元测试中所做的非常相似,并且相同的代码表现不同:

 myItems = myRepo.GetForId(Guid.Empty);

 if (!myItems?.Any() ?? true)
 {
    //debugger stops here
 }
 else
 { 
 }

鼠标悬停显示myItems.Count==1 这应该导致谈论else分支。 我真的不知道这是怎么可能的..

更新

enter image description here

0 个答案:

没有答案