resharper是否正确无法访问此代码?

时间:2014-02-27 21:02:47

标签: c# resharper nullable

Reshaper表示??的左侧永远不会为空,即使其类型为int?

        _savedMediaFileId = mediaFile.MediaFileId ?? _savedMediaFileId;

自动重构“删除无法访问的代码”将其转换为:

        _savedMediaFileId = (int) mediaFile.MediaFileId;

这是对的还是Resharper在这里犯了错误?

我的想法是因为int?可以为空,那么我可以使用??保留现有值,如果它为null。

这是我的单元测试(正在进行中)

[TestClass]
public class MediaRepositoryTest
{
    private const string SiteId = "3";

    private const string ConnectionString =
        @"Data Source=dvmind\mssqlsites;Database=***********;User Name=sa;Password=**************";

    private string _mediaSourceName = "TestMediaSourceName";
    private string _mediaTypeName = "TestMediaTypeName";
    private string _mediaSourceAddress = "TestMediaSourceAddress";
    private string _mediaFileAddress = "TestMediaFileAddress";

    private int _savedMediaFileId = 0;

    private string GetGuidString()
    {
        return Convert.ToBase64String(Guid.NewGuid().ToByteArray());
    }

    [TestInitialize]
    public void TestInitialize()
    {
        _mediaSourceName = _mediaSourceName + GetGuidString();
        _mediaTypeName = _mediaTypeName + GetGuidString();
        _mediaSourceAddress = _mediaSourceAddress + GetGuidString();
        _mediaFileAddress = _mediaFileAddress + GetGuidString();
    }

    [TestCleanup]
    public void TestCleanup()
    {
        using (var db = new SiteContext(ConnectionString))
        {
            if (_savedMediaFileId != 0)
            {
                (from c in db.MediaFiles where c.MediaFileId == _savedMediaFileId select c).ToList()
                    .ForEach(c => db.MediaFiles.Remove(c));
            }

            (from c in db.MediaSources where c.MediaSourceName == _mediaSourceName select c).ToList()
                .ForEach(c => db.MediaSources.Remove(c));

            (from c in db.MediaTypes where c.MediaTypeName == _mediaTypeName select c).ToList()
                .ForEach(c => db.MediaTypes.Remove(c));
        }
    }

    [TestMethod]
    public void SaveMediaTest()
    {
        var mediaSource = new MediaSource
        {
            MediaSourceName = _mediaSourceName,
            MediaSourceAddress = _mediaSourceAddress
        };

        var mediaType = new MediaType
        {
            MediaTypeName = _mediaTypeName
        };

        var mediaFile = new MediaFile
        {
            SiteId = SiteId,
            MediaFileAddress = _mediaFileAddress,
            MediaSource = mediaSource,
            MediaType = mediaType
        };

        var connectionStringProvider =
            Mock.Of<IConnectionStringProvider>(c => c.GetConnectionString() == ConnectionString);

        var repository = new MediaRepository(connectionStringProvider);

        Assert.IsTrue(mediaFile.MediaFileId == 0);

        repository.SaveMedia(mediaFile);

        Assert.IsTrue(mediaFile.MediaFileId != 0);

        _savedMediaFileId = mediaFile.MediaFileId ?? _savedMediaFileId;

        //using (var db = new SiteContext(ConnectionString))
        //{  
        //}
    }

3 个答案:

答案 0 :(得分:3)

现在您已经发布了一个完整的示例,我认为您获得无法访问的代码的原因是由于此行之前的Assert条件;

Assert.IsTrue(mediaFile.MediaFileId == 0);

如果mediaFile.MediaFileId为null,程序退出此行,如果不是,则警告正确; mediaFile.MediaFileId在您突出显示的行上不能为空;

_savedMediaFileId = mediaFile.MediaFileId ?? _savedMediaFileId;

此外,如果SaveMedia的定义采用了ref MediaFile也会影响警告,因为可能(就ReSharper而言)该值再次更改为Null by ;

repository.SaveMedia(mediaFile);

这些更改都会影响警告的存在。

答案 1 :(得分:2)

ReSharper可能会在此推断mediaFile.MediaFileId永远不会有值null,即使类型为int?。因此,它建议您完全跳过null检查并直接获取值

更清晰的例子是以下

string s = "hello world";
if (s != null) { 
  ...
}

在这种情况下,s实际上可能是null,因为它属于string类型而null是有效值。但是在此特定上下文中s永远不会是null因此ReSharper会将此检查标记为不必要

答案 2 :(得分:0)

这是一个猜测,但我认为这里发生了什么(基于MSDN

当你声明某些int?时,它不会创建一个可以为null的引用类型。相反,它会创建Nullable<T>,这是struct,意味着它不能为空b / c它是值类型。除了值之外的那个结构包含一个布尔标志,告诉它是否为null,如果值有效。

因此,做int? ??本质上是测试一个结构为空值,它永远不会。它不测试Nullable<T>.HasValue哪种方法可以测试是否为“null”。

因此ReSharper投诉。