C# 从缓存中获取对象时,代码是启发式不可访问的

C# 从缓存中获取对象时,代码是启发式不可访问的,c#,resharper,fxcop,C#,Resharper,Fxcop,我有下面的代码,想法很简单,如果对象在缓存中获取它,如果没有,那么从数据源检索它并将其保存到缓存中,我使用的是resharper,我得到了这个警告,但不理解为什么 public static ModulosPorUsuario GetModulesForUser(string identityname) { // It needs to be cached for every user because every user can have differ

我有下面的代码,想法很简单,如果对象在缓存中获取它,如果没有,那么从数据源检索它并将其保存到缓存中,我使用的是resharper,我得到了这个警告,但不理解为什么

 public static ModulosPorUsuario GetModulesForUser(string identityname)
        {
            // It needs to be cached for every user because every user can have different modules enabled.
            var cachekeyname = "ApplicationModulesPerUser|" + identityname;

            var cache = CacheConnectionHelper.Connection.GetDatabase();
            ModulosPorUsuario modulosUsuario;

            //get object from cache
            string modulosUsuariosString = cache.StringGet(cachekeyname);

            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
            if (modulosUsuariosString != null)
            {
                //conver string to our object
                modulosUsuario = JsonConvert.DeserializeObject<ModulosPorUsuario>(modulosUsuariosString);
                return modulosUsuario;
            }
            // ReSharper disable once HeuristicUnreachableCode
            modulosUsuario = DbApp.ModulosPorUsuario.Where(p => p.Email == identityname).FirstOrDefault();

            //convert object to json string
            modulosUsuariosString = JsonConvert.SerializeObject(modulosUsuario);

            //save string in cache
            cache.StringSet(cachekeyname, modulosUsuariosString, TimeSpan.FromMinutes(SettingsHelper.CacheModuleNames));
            return modulosUsuario;
        }
publicstaticmodulesorusuariogetmodulesforuser(stringidentityname)
{
//它需要为每个用户缓存,因为每个用户都可以启用不同的模块。
var cachekeyname=“ApplicationModulesPerUser |”+identityname;
var cache=CacheConnectionHelper.Connection.GetDatabase();
ModulesOrusuario ModulesSuario;
//从缓存中获取对象
string moduleSuariosString=cache.StringGet(cachekeyname);
//ReSharper disable once ConditionIsAlwaysTrueOrFalse
if(modulesUserAsString!=null)
{
//将字符串转换到我们的对象
ModuleSuario=JsonConvert.DeserializeObject(ModuleSuarioString);
返回模块化;
}
//ReSharper禁用once HeuristicUnreachableCode
modulesSuario=DbApp.modulesOrusuario.Where(p=>p.Email==identityname).FirstOrDefault();
//将对象转换为json字符串
ModuleSuarioString=JsonConvert.SerializeObject(ModuleSuario);
//在缓存中保存字符串
StringSet(cachekeyname,moduleSuariosString,TimeSpan.FromMinutes(setingShelper.CacheModuleNames));
返回模块化;
}

这里发生了很多事情,但归根结底,这是一个ReSharper错误-值当然可以为null,我有一个小得多的例子来证明这一点

首先,让我们了解代码中发生了什么。我得在你正在使用的图书馆里挖点东西。实际上,
cache
对象是一个
IDatabase
,由类实现。您正在使用的方法返回一个
RedisValue
,它是一个结构。这本身就很有道理,为什么ReSharper告诉您它永远不能为null-值类型不能

但是,您正在将结果放入
字符串
变量中!这是因为
RedisValue
struct定义了一组将值转换为请求类型的方法。对于字符串,请注意,如果blob为空,则返回空字符串:

我把这个问题告诉JetBrains,他们会解决的


同时,您可能希望保留该注释,禁用ReSharper警告。

是否cache.StringGet总是返回字符串,因此您的if条件将始终为true,从而使其余代码无法访问?我认为@user995219是正确的,特别是因为您还禁用了ReSharper警告,告诉您这一点。如果(!string.IsNullOrEmpty(moduleSuariosString))
,您可能需要执行
,但这实际上取决于
StringGet()
为缓存未命中返回的内容(我认为
null
更为正确)比
string.Empty
,虽然仍然不是一个很好的缓存API,因为它意味着你不能将结果缓存为
null
)你怎么知道这是正在使用的库@AakashM magic:P但老实说,我只是在谷歌上搜索了
CacheConnectionHelper.Connection.GetDatabase
,发现在各种“Azure Redis缓存”帖子中都提到了它。
/// <summary>
/// Converts the value to a String
/// </summary>
public static implicit operator string(RedisValue value)
{
    var valueBlob = value.valueBlob;
    if (valueBlob == IntegerSentinel)
        return Format.ToString(value.valueInt64);
    if (valueBlob == null) return null;

    if (valueBlob.Length == 0) return "";
    try
    {
        return Encoding.UTF8.GetString(valueBlob);
    }
    catch
    {
        return BitConverter.ToString(valueBlob);
    }
}
static void Main(string[] args)
{
    string value = MyStruct.GetValue();
    if (value == null) // <- ReSharper complains here, but the value is null!
    {
        return;
    }
}

public struct MyStruct
{
    public static MyStruct GetValue() => new MyStruct();

    public static implicit operator string(MyStruct s)
    {
        return null;
    }
}