I have the following code, the idea is simple if the object is in cache get it, if not then retrieve it from the data source and save it into cache, I am using resharper and I got this warning but cant understand why
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;
}
There's quite a lot going on here, but the bottom line, this is a ReSharper bug - the value can certainly be null, and I have a much smaller example proving it.
First, let's figure out what's going on in your code. I had to dig a little bit into the StackExchange.Redis
library that you're using. Your cache
object is, in fact, an IDatabase
, which is implemented by the RedisDatabase
class. The StringGet
method that you're using returns a RedisValue
, which is a struct. This, by itself, would make perfect sense why ReSharper tells you it can never be null - value types can't!
However, you're putting the result into a string
variable! This works because the RedisValue
struct defines a bunch of implicit operators to convert the value into the requested type. In case of a string, notice that if the blob is empty, an empty string is returned:
/// <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);
}
}
But from this code it's obvious that the string can be null
as well.
This makes ReSharper incorrect to flag that line, and it can be reproduced with a smaller example:
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;
}
}
I reported this issue to JetBrains, they will fix it.
In the meantime, you might want to keep that comment, disabling ReSharper warning.