I have a problem resolving this CS8603 warning. Even though there is a null-check for resource variable, null reference is still possible. How come?
Code:
public string GetResource(string resourcePath)
{
var resource = Application.Current.Resources[resourcePath];
if (resource == null)
{
return $"{ResourceError} [{resourcePath}]";
}
// ToDo: CS8603
return resource.ToString();
}
You did correctly check wether resource is null. But even if it is not, ToString() might return null. You can use something like
return resource.ToString() ?? "";
Related
So basically I want to check that a setting is not set in my C# application. The code here
if (Default["StudentAccountTypeDefault"] is null) // Crashes after this
{
//
}
else
{
//
}
seems to be crashing on the null-check. I've put a breakpoint there, and it shows Default["DefaultStudentAccountType"] to just be a blank string. Why is it crashing with a NullReferenceException? I'm pretty sure this is where it crashes-if I comment out if statement it works as expected.
Edit: To alleviate some confusion. Sooooo, Default is actually Settings.Default, and to add to that, I was actually trying to access it inside the Settings() constructor. So, before it had been initialized, obviously. Oops. "Full"-er code below.
public Settings() {
// // To add event handlers for saving and changing settings, uncomment the lines below:
//
// this.SettingChanging += this.SettingChangingEventHandler;
//
// this.SettingsSaving += this.SettingsSavingEventHandler;
//
if (Settings.Default["DefaultStudentAccountType"] is null)
{
}
else
{
}
}
You should be checking with == not with is, also depending on your data type you may need to check if Default is null too. Try this:
if(Default == null || Default["StudentAccountTypeDefault"] == null)
{
}
else
{
}
Default is a variable, so if it is null, accessing the indexer ["StudentAccountTypeDefault"] will throw a null reference exception.
If you're using a new enough .NET version, you can use:
if (Default?["StudentAccountTypeDefault"] is null)
(the null-coalescing operator). Otherwise, just check Default for null before using its indexer.
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:
RedisValue.cs
/// <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.
Take the following:
obj myVar;
and
obj myVar = null;
Is there an actual difference between these two - and are they both caught by (myVar == null)?
Your answer is in your question. obj != null means "the object exists".
However, this is only true almost all the time. A custom override of the == and != operator can change this functionality, so to be absolutely sure you can use !Object.ReferenceEquals(obj,null) to ensure that the object does exist, in all cases.
The error you are getting is a System.NullReferenceException, and will always be averted by this check.
The short, but sweet, answer is: the check (object != null) always prevents object not set to an instance
Worth mentioning
If you are reading objects from a database like in the snippet of code below:
private object GetItem(DataSet dataSet1, string tableName, int row, int col) {
object obj = null;
try {
obj = dataSet1.Tables[tableName].Rows[row][col];
} catch (Exception err) {
Console.WriteLine(err.Message);
}
return obj;
}
The returned value could be null (if an exception were caught) or DBNull.Value if dataSet1.Tables[tableName].Rows[row][col] was not set in the database.
If, however, you neglect to initialize object obj as in the example below:
private object Test2(DataSet dataSet1) {
object obj;
try {
obj = dataSet1.Tables[0].Rows[0][0];
} catch (Exception err) {
Console.WriteLine(err.Message);
}
return obj;
}
The code will not compile under Visual Studio.
That is the same thing. If an object is not set to an instance of an object, it will have not have a reference to anything, and will in other words, be null.
Below is the code and the problematic line.
When I hover with the mouse on src.EnergyServiceLevel, it shows that it's null.
How can that be if I'm checking for null in the previous line?
My guess was that maybe there are threads that making the problem so I've add a lock,
but it didn't helped.
public static ServiceLevelsGroup SafeClone(this ServiceLevelsGroup src) {
ServiceLevelsGroup res = null;
lock (_locker) {
if (src != null) {
res = new ServiceLevelsGroup();
if (src.EnergyServiceLevel != null) {
res.EnergyServiceLevel = new ServiceLevelInfo { ServiceGrade = src.EnergyServiceLevel.ServiceGrade };
if (src.EnergyServiceLevel.Reason != null)
res.EnergyServiceLevel.Reason = src.EnergyServiceLevel.Reason;
}
}
}
return res;
}
The exception occurs at the res.EnergyServiceLevel = ... line in the above code.
Here's a screenshot of the exception occurring in debug mode:
Your code shows lock(_locker) - so it looks like you're in a multithreaded environment. Can you check that nothing else is NULLing your variable? i.e. that everything else is also calling lock(_locker) correctly?
Maybe your NULL is at res.EnergyServiceLevel.
src.EnergyServiceLevel.ServiceGrade may be null
Moving mouse pointer to each reference will exactly show you which is null.
Which is the most correct code?
if (HttpContext.Current.Response.Cookies[authCookieName] != null) {
HttpContext.Current.Response.Cookies[authCookieName].Value = "New Value";
}
or
if (HttpContext.Current != null)
if (HttpContext.Current.Response != null)
if (HttpContext.Current.Response.Cookies != null)
if (HttpContext.Current.Response.Cookies[authCookieName] != null)
HttpContext.Current.Response.Cookies[authCookieName].Value = "New Value";
If any one of HttpContext, HttpContext.Current, HttpContext.Current.Response, or Http.Current.Response.Cookies is null, you're already in trouble. Let the exception happen and fix your web server.
Both are good. Assuming that you have already checked everything else that need to be checked first. E.g.:
private bool CheckSuspendersAndBelt()
{
try
{
//ensure that true is true...
if (true == true)
{
//...and that false is false...
if (false == false)
{
//...and that true and false are not equal...
if (false != true)
{
//don't proceed if we don't have at least one processor
if (System.Environment.ProcessorCount > 0)
{
//and if there is no system directory then something is wrong
if (System.Environment.SystemDirectory != null)
{
//hopefully the code is running under some version of the CLR...
if (System.Environment.Version != null)
{
//we don't want to proceed if we're not in a process...
if (System.Diagnostics.Process.GetCurrentProcess() != null)
{
//and code running without a thread would not be good...
if (System.Threading.Thread.CurrentThread != null)
{
//finally, make sure instantiating an object really results in an object...
if (typeof(System.Object) == (new System.Object()).GetType())
{
//good to go
return true;
}
}
}
}
}
}
}
}
}
return false;
}
catch
{
return false;
}
}
(sorry, couldn't resist... :) )
could try:
if(HttpContext.Current != null &&
HttpContext.Current.Response != null &&
HttpContext.Current.Response.Cookies != null &&
HttpContext.Current.Response.Cookies[authCookieName] != null)
{
// do your thing
}
HttpContext.Current.Response.Cookies will never be null. The only thing that can cause a null is if the cookie you are expecting doesn't exist, so the first is correct. HttpContext.Current would be null if you weren't accepting a web request though :)
The first example you gave is more than enough. Like mentioned, if any of the other objects are null there is a problem with ASP.NET.
if (HttpContext.Current.Response.Cookies[authCookieName] != null) {
HttpContext.Current.Response.Cookies[authCookieName].Value = "New Value";
}
But rather than littering your code with these often many checks, you should create some generic functions like SetCookie, GetCookie, GetQueryString, and GetForm, etc. which accept the name and value (for Set functions) as parameters, handle the null check, and returns the value or an empty string (for Get Functions). This will make your code much easier to maintain and possibly improve, and if you decide to use something other than Cookies to store/retrieve options in the future, you'll only have to change the functions.
Neither is really more correct, though I would avoid the second, as deeply nested conditionals tend to be hard to understand and maintain.
If you would prefer you get a null pointer exception, use the first. If you want to deal with nulls in another way or silently, use the second (or a refactored version of the second).
If you think there's a chance that Current, Response, Cookies, or Cookies[authCookieName] could be null, and you have a reasonable thing to do if any of them are, then the latter's the way to go. If the chances are low, and/or there's nothing you can do if the intermediates are null, go for the former, as it's more concise - the best you could do is to get better logging if you use the expanded example.