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.
Related
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() ?? "";
I'm running into an odd scenario that doesn't happen on my PC, but does for a coworkers.
I have this piece of code:
LoaderHelpers.SetStringValue<blah>(this, "x", $"x response in Header",
() => jsonData.x.response[0].value, false);
The problem is that sometimes, "jsonData.x" is null and, for my coworker a 'cannot bind to null at runtime exception' is thrown, but not for me there isn't. I have code to handle the null scenario, but it's like his code never gets to that point and fails at the call level.
jsonData is of type dynamic.
The method code that handles the null scenario:
public static void SetStringValue<T>(IValidate data, string propertyName,
string valuePath, Func<string> value, bool required)
{
if (data.GetType().GetProperty(propertyName) != null)
{
try
{
if (string.IsNullOrEmpty(value()))
{
if (required)
data.DataValidationErrors.Add($"{valuePath} can't be empty");
data.GetType().GetProperty(propertyName).SetValue(data, null);
}
else
{
data.GetType().GetProperty(propertyName).SetValue(data, value());
}
}
catch
{
//property doesn't exist
if (required)
data.DataValidationErrors.Add($"{valuePath} doesn't exist");
data.GetType().GetProperty(propertyName).SetValue(data, null);
}
}
else
{
throw new NullReferenceException($"In {data.GetType()} => SetStringValue. " +
$"Passed property {propertyName}, but property doesn't exist.");
}
}
Again. Works perfect for me, but not for him. I'm completely lost. Maybe I don't understand how the lamba/function parameters work 100%, but I thought it only got evaluated when value() is invoked.
I should also mention that when I debug this code, I can step into the Nuget package and when he hits the same line, he can't. This maybe a useful hint.
If jsonData (or jsonData.x) is null (as it seems to be at this point) it will crash and give you that error every time you call the method value().
You need to check why jsonData.x is null. Maybe it´s a race condition caused by another thread setting this value to null, maybe it´s because a bad jsonData initialization... Can´t say since that code is not here.
There are so many things wrong with your code, i can't resist.
First of all, instead of copy/pasting the same stuff over and over, you might want to use a variable:
var property = data.GetType().GetProperty(propertyName);
Second, you pass a Func<string> and execute it multiple times, why is it even a function then? Yet again, better only evaluate it once and use a variable...
var unwrapped = value();
That would solve the issue, that Roberto Vázquez' answer adresses.
Then you are misusing NullReferenceException, instead rather use a ArgumentException
Next issue, that valuePath is only used in the exception message, that is a poor design to my beliefs.
The generic T parameter isnt even used, so get rid of it.
Last but not least, that catch-block doing the exact thing that could possibily throw the exception again, i cant see any reason why you would do this.
Finnaly this whole thing becomes a little more clear but its still a mess.
public static void SetStringValue(IValidate data, string propertyName,
string valuePath, Func<string> value, bool required)
{
if(data == null)
throw new ArgumentNullException(nameof(data));
var property = data.GetType().GetProperty(propertyName);
if(property == null)
throw new ArgumentException($"In {data.GetType()} => SetStringValue. " +
$"Passed property {propertyName}, but property doesn't exist.");
var unwrapped = value();
try
{
if (string.IsNullOrEmpty(unwrapped))
{
if (required)
data.DataValidationErrors.Add($"{valuePath} can't be empty");
unwrapped = null; // this might be unecessary.
}
property.SetValue(data, unwrapped);
}
catch(Exception e)
{
// This is probably a bad idea.
property.SetValue(data, null);
if (required)
data.DataValidationErrors.Add(Atleast put a better message here. e.Message ...);
}
}
Having an odd problem. It's happened a few times over the years, but I've never been able to figure out why. Always solved it by rearranging the code I had in place, but would like to know is there's a more proper way of dealing with it, or at least figuring out what's behind it.
Non-working version:
public bool CaptureFrame(ArrayCache cache)
{
if (cache == null)
throw new ArgumentNullException("cache");
DataArray frame = cache.CacheData;
if (frame == null)
throw new ArgumentNullException("cache.CacheData");
// do stuff
}
Working version:
public bool CaptureFrame(ArrayCache cache)
{
if (cache == null)
throw new ArgumentNullException("cache");
if (cache.CacheData == null)
throw new ArgumentNullException("cache.CacheData");
DataArray frame = cache.CacheData;
// do stuff
}
The problem is this: frame is not null (at least according to the debugger, and by any measure I can trace of the code), however when it does the if (frame == null) check, it comes out true and throws the exception. I rewrote to check cache.CacheData and it works fine, but it really shouldn't make any difference to the code logic.
I managed to find one other question on the site with a similar problem, which ended up being related to the == and != operators being overloaded. Those operators are not overloaded for the class in question in my code, and it's a standalone class so there's nothing for it to inherit.
Edit: John Saunders requested code for the CacheData property:
private DataArray cacheData;
public DataArray CacheData
{
get
{
return cacheData;
}
set
{
cacheData = value;
}
}
looks like you are mapping the exception in the non working one then calling
DataArray frame = cache.CacheData;
but what if cache.CacheData if null then you are assigning it to DataFrame.. it's always best in my opinion to do the Check for null first before assigning or assuming your second one looks fine.. prehaps instead of throwing an exception maybe you could trap the exception and try some test cases for both scenarios
Is it legal to make the following statement:
if(Cache[CACHE_KEY] == null)
{
//do something to form cache
}
else
{
//do something else that uses cache
}
I'm not sure my program is actually functioning properly (even though it compiles) and am wondering if a cache doesn't exist is it set to null?
Yes, that is legal (but the question in the title is not, see below for details).
Though, it may be wise to check that the type in the cache is what you're expecting rather than having to do this check twice, such as:
//in English, the following line of code might read:
// if the item known in the cache by the specified key is in
// in fact of type MyExpectedReferenceType, then give me it
// as such otherwise, give me a null reference instead...
var myCachedInstance = Cache[key] as MyExpectedReferenceType;
if (myCachedInstance == null)
{
//we retrieved a reference to an instance of an MyExpectedReferenceType
}
else
{
//oh, no - we didn't!
}
On re-reading your question though, and thinking about your program not working properly, I'm tempted to say you have bigger issues than this; how is your program not working correctly? The Cache instance itself will never be null while accessible - it is a read-only field of Page. However, your expected cached value could be null and, if this is the problem, you should be receiving a NullReferenceException - is that the case?
UPDATE:
To address your comment, check out the comments I added to the code.
Very much legal; rather its better to check for a value before performing action, especially to make sure that key has not slided-out, or expired, etc.
There is a potential race condition in the code you posted:
if(Cache[CACHE_KEY] == null)
{
//do something to form cache
}
else
{
// Another thread could have removed CACHE_KEY from the Cache before you get here
}
It's better to first extract the object from the cache, then test it for null, e.g.:
MyObject cachedObject = Cache[CACHE_KEY] as MyObject;
// or MyObject cachedObject = (MyObject) Cache[CACHE_KEY]; if you know it is of type MyObject
if(cachedObject == null)
{
cachedObject = ... // generate the cached object
Cache.Insert(CACHE_KEY, cachedObject, ...);
}
// use cachedObject
Yes it`s possible, Cache will always be initialize (like session and application obj)
But you can check if a key in the cache 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.