Cache == null? Is it possible? - c#

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

Related

Alternative to a monitor to checking for the existence of a record, and writing it if it doesn't exist

So I have a bit of C# code that looks like the below (simplified for the purpose of the question, any bugs are from me making these changes). This code can be called from multiple threads or contexts, in an asynchronous fashion. The whole purpose of this is to make sure that if a record already exists, it is used, and if it doesn't it gets created. May or may not be great design, but this works as expected.
var timeout = TimeSpan.FromMilliseconds(500);
bool lockTaken = false;
try
{
Monitor.TryEnter(m_lock, timeout, ref lockTaken); // m_lock declared statically above
if (lockTaken)
{
var myDBRecord = _DBContext.MyClass.SingleOrDefault(x => x.ForeignKeyId1 == ForeignKeyId1
&& x.ForeignKeyId2 == ForeignKeyId2);
if (myDBRecord == null)
{
myDBRecord = new MyClass
{
ForeignKeyId1 == ForeignKeyId1,
ForeignKeyId2 == ForeignKeyId2
// ...datapoints
};
_DBContext.MyClass.Add(myDBRecord);
_DBContext.SaveChanges();
}
}
else
{
throw new Exception("Can't get lock");
}
}
finally
{
if (lockTaken)
{
Monitor.Exit(m_lock);
}
}
The problem occurs if there are a lot of requests that come in, it can overwhelm the monitor, timing out if it has to wait too long. While the timeout for the lock can certainly be shorter, what is the preferred approach, if any, to addressing this type of a problem? Anything that would try to see if the monitor'd code needed to be entered would need to be part of that atomic operation.
I would suggest that you get rid of the monitor altogether and instead handle the duplicate key exception. You have to handle the condition where you are trying to enter a duplicate value anyway, why not do so directly?

C# lambda null runtime binding

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 ...);
}
}

Activator.CreateInstance works in one method but throws AmbiguousMatchException in another

I have two generic methods in the same class, and each uses exactly the same code to create instances. One works, the other throws an AmbiguousMatchException. Here is the code:
private static Dictionary<Type, AccessBase> _dictionary;
public static T Access<T>(Type type) where T : AccessBase
{
T instantiated;
if (_dictionary.ContainsKey(type))
{
instantiated = _dictionary[type] as T;
}
else
{
instantiated = (T)Activator.CreateInstance(type, _manager); //<- Works!
_dictionary.Add(type, instantiated);
}
return instantiated;
}
public static void RegisterAccess<T>(Type type) where T : AccessBase
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (_dictionary.ContainsKey(type))
{
return;
}
var instantiated = (T)Activator.CreateInstance(type, _manager); //<- Fails!
if (instantiated == null)
{
throw new ArgumentException($"{nameof(type)} cannot be registered");
}
_dictionary.Add(type, instantiated);
}
I would welcome any suggestions as to why and what to do about it... I have been tearing what is left of my hair out over this one!
Thanks to all of you for your input. I finally found the problem, which as it turns out is quite simple actually. At the point of failure the value of the _manager field is null... As soon as it is no longer null, it works.
To trap this I tried calling the first method at the same time as the second, and both failed. Tracking it through, I determined that the cause was the null value, since if you do it later in the process it works fine.
The original purpose of the code was to pre-register the access classes so that when they are needed they are ready to go and avoid the constant 'new' calls to generate these classes as they are needed. Given that it is now clear that this cannot happen at that point, the question is whether this is required at all. If we do it at a later point, there is not much reason to do it as it will get repeated every time a database is opened with each one not being added as it already exists.
I think we will end up abandoning the process that uses the second method, the pre-registration, in favour of the first method which is already used anyway and which automatically adds the instantiated classes only when they are needed and which already works fine at the later point.

Why is this null check incurring a null dereference error?

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.

Using Reflection to get the field/property that is being null compared?

How do I know the log the last property that is null?
For example,
var a = "somevalue";
......
......
if(a == null)
{
Log.Error(MethodBase.GetCurrentMethod().Name + "Property : a is null");
//blah blah
}
Like how I use the reflection to get the current method name, there should be some means by which I can log the latest local variables (or a property or fields)
that is being compared ? I use, log4net by the way to log the errors.
1) Is there any method to achieve this or should we manually log it?
2) Is there any custom method that prints the class -> MethodName -> Propertyname(or FieldName) that is null?
Thanks for your time in advance.
As mentioned by #fsimonazzi, "a" would be a local variable.
That being said there is still no way to examine the current compare operation as in MSIL there is no formal concept of an IF block - only conditional jumps.
If you wanted to get really crazy with the reflection, you may be able to find the current executing instruction and look around near that for a variable, but even then, you will not find the name - only a reference - as names are only used prior to compilation.
Either way, reflection is not going to help you here.
Instead, try using Exceptions - specifically ArgumentNullException. This body of code would become:
void doStuff(string param1, int param2)
{
if (param == null)
throw new ArgumentNullException("param1", "param1 must not be null");
if (param2 < 0)
throw new ArgumentOutOfRangeException("param2", "param2 should be non-negative.");
//method body
}
then, when you call the method, you can catch the exception and log it - no matter what it may be.
public static void Main(string[] args)
{
try
{
doStuff(null, 3);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Tools like FxCop can help make sure that you are properly validating each parameter.
Properties are actually implemented as methods, so reflection could help you there. If, for example, you were validating in a property and wanted to log the position automatically, you could.
private object _cachedObject = null;
public object CachedObject
{
get
{
if (_cachedObject == null)
{
log(MethodBase.GetCurrentMethod().Name, "creating cached object");
_cachedObject = createCachedObject();
}
return _cachedObject;
}
}
The .Net Framework 4.5 also brings with it a new attribute that can be used to replace the MethodBase.GetCurrentMethod().Name construct you are using to get the method name. See [CallerMemberNameAttribute][3].

Categories

Resources