I'm upgrading a system and am going through another developers code (ASP.NET in C#).
I came across this:
private ReferralSearchFilterResults ReferralsMatched
{
get
{
if (Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] == null || Session[SESSION_REFERRAL_SEARCHFILTERRESULTS].GetType() != typeof(ReferralSearchFilterResults))
return null;
else
return (ReferralSearchFilterResults)Session[SESSION_REFERRAL_SEARCHFILTERRESULTS];
}
set
{
if (value == null)
{
Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] = value;
}
else if (value.GetType() == typeof(ReferralSearchFilterResults))
{
Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] = value;
}
}
}
Is checking the type on the setter unnecessary? Surely, if I set the property to something other than a ReferralSearchFilterResults object, the code wouldn't even compile? Am I missing something or am I right to think this can be achieved just by using:
set
{
Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] = value;
}
The original code prevents any subclasses of ReferralSearchFilterResults from being set or get to or from the property. This is because value.GetType() will return the actual Type of the object referenced by value. If that Type is a subclass of ReferralSearchFilterResults, then it will not equals typeof(ReferralSearchFilterResults).
I'm not sure of your context here, so I can't tell you whether that's correct behaviour or not. If it's intended behaviour, it does smell a bit dirty as it will silently ignore any assignments of subclasses. But I can't really judge without more context.
I think you're right - the setter shouldn't compile if provided with something of that cannot be implicitly cast to a ReferralSearchFilterResults.
For the get part, you can use
return Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] as ReferralSearchFilterResults;
This returns the value if it can be casted to ReferralSearchFilterResults, otherwise null.
Jamie you are correct. The Type check on the Setter is unnecessary in this case because value must be a ReferralSearchFilterResults.
One other change you might consider is using the is and as keywords in place of comparing Type objects.
private ReferralSearchFilterResults ReferralsMatched
{
get
{
if (Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] == null || !(Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] is ReferralSearchFilterResults))
return null;
else
return Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] as ReferralSearchFilterResults;
}
set
{
Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] = value;
}
}
Session variables are of type object, so you can store anything inside those. But in this case the setter itself prevents the programmer from assigned an other object type than ReferralSearchFilterResults and derived objects.
So the check, as you pointed out, itself is unneccessary. Additionally it does not let a programmer assign a object that derives from ReferralSearchFilterResults.
But I would use Session.Remove rather than just setting the variable to null, because the session variable would still exists in the http context if only set to null.
So:
set
{
if (value == null)
Session.Remove(SESSION_REFERRAL_SEARCHFILTERRESULTS);
else
Session[SESSION_REFERRAL_SEARCHFILTERRESULTS] = value;
}
I can understand the type check in the get bit, but as you say, in the setter, you can't pass in anything that's not a ReferralSearchFilterResults, as the code would fail at the time of compilation.
(Could be some old habit, the other developer had)
Related
I am having trouble using an IList property which always seems to return null, even though the member is is getting is instantiated:
private List<ModelRootEntity> _validTargets = new List<ModelRootEntity>();
public IList<IModelRootEntity> ValidTargets
{
get
{
return _validTargets as IList<IModelRootEntity>;
}
protected internal set
{
if (value == null)
_validTargets.Clear();
else
_validTargets = value as List<ModelRootEntity>;
}
}
ModelRootEntity implements IModelRootEntity. I watched both values during debugging, whilst the member shows a positive count, the property stays null.
I also tried raising an exception within the property getter to throw if the counts of _validTargets and _validTargets as List<ModelRootEntity> are different, but it never threw.
Found question [Dictionary properties are always null despite dictionaries being instantiated, which seems similar, however in my case this seems to happen regardless of serialization.
Any ideas?
If you set your property to any value that isn't a List<ModelRootEntity>, the as expression will return null and the property will become null.
I found the answer, thanks to #Nilesh comment above.
Replacing:
private List<ModelRootEntity> _validTargets = new List<ModelRootEntity>();
with:
private List<IModelRootEntity> _validTargets = new List<ModelRootEntity>();
exposed the real issue. The second line will not compile. The following post explained why:
C# newbie List<Interface> question
The only odd thing was the exception I tried to force which never threw, and "threw" me off.
Ight, so i love one liners, and I've gotten pretty good as condensing all kinds of stuff. For some reason they make me happy, and they help me learn. The highlights of the life of a computer programmer!
So anyways, i need help with this one with a casted object assignment:
Here's an example of a simple property:
protected InterfaceType Object{
get{ return (InterfaceType)this.Page;} // no red squigglies, works fine
set{ (InterfaceType)this.Page = value; } // red squigglies(left hand of argument must be a variable, property or indexer)
}
However i could do this:
protected InterfaceType Object{
get{ return (InterfaceType)this.Page;} // no red squigglies, works fine
set{ var o = (InterfaceType)this.Page; o = value; } // works fine
}
If (InterfaceType)this.Page returns an object as evident by:
return (InterfaceType)this.Page;
And i can assign it to stuff:
var o = (InterfaceType)this.Page;
And assign stuff to it:
o = value;
To me, i feel like i'm creating a new unnecessary pointer to something; since the below is just a pointer to this object in itself if i can retrieve it with it:
(InterfaceType)this.Page
You probably need to remove extra semi-colon after this.page and remove type casting.
Change
set{ (InterfaceType)this.Page; = value; }
To
set{ this.Page = value; }
There are several issues here. If this.Page was declared as an instance of InterfaceType, there'd be no casting necessary at all.
That indicates that you're trying to downcast an instance of InterfaceType to whatever type Page is in the setter. Obviously, that's not safe and your cast isn't going to work anyway. I would change it to:
set { this.Page = (value as WhateverTypePageIs); }
This means that your setter will no longer throw an Exception if the cast is invalid, it will simply set this.Page to null. If that's not desirable, you could use:
set { this.Page = ((WhateverTypePageIs)value); }
Which would still throw the Exception.
All of this, though, points to a deeper issue. If you want to have setter but store the value as a more specific type, you should make Object be the same type as this.Page so you make that restriction clear to any callers.
You must cast the right hand side of the expression to the desired type:
set{ this.Page = (InterfaceType)value; }
However, reading your code, it is entirely possible that Page is defined as a lesser type in the inheritance hierarchy; in which case no cast is necessary:
set { this.Page = value; }
So, First of all. Code:
I've got a class:
public class Myobject
{
public string Code { get; set; }
public DateTime? StartDate { get; set; }
}
And this is part of very simple source:
MyObject mo = new MyObject();
mo.Code= "sth";
// NO action on StartDate property!
if (mo.StartDate.HasValue)
{
sc.Parameters.Add(new SqlParameter("#inStartDate", mo.StartDate.Value));
}
else
{
sc.Parameters.Add(new SqlParameter("#inStartDate", DBNull.Value));
}
Simple 'if' - Sql Server 2008, throw an error - when gets null Datetime (it has to be DBNull.Value)
So I want to check it first, and then pass right value or DBNull.
My problem is - this 'if' always retruns true! Why!?
Also tried that:
if (mo.StartDate.Value == null)
but it always returns false. How come it is not a null? It was not even created..
So.. How to check if DateTime object was not assigned?
Try this:
if (mo.StartDate.GetValueOrDefault() != DateTime.MinValue)
{
// True - mo.StartDate has value
}
else
{
// False - mo.StartDate doesn't have value
}
should just be able to do
mo.StartDate != null
instead of
mo.StartDate.Value != null
Running the simplest test with that class (as you presented it) yields false:
var mo = new Myobject();
Console.WriteLine(mo.StartDate.HasValue);
Output is False.
I'd put a breakpoint on your constructor (if you have one), make sure nothing else is getting assigned, and walk through any methods called along the way to make sure there's nothing else setting the property that may not be immediately obvious...
Can you post more code, perhaps? There must be something in code not posted setting the property.
.HasValue and ==null are the ways to check whether DateTime? is assigned a value or not. You are doing it right. There might be problem somewhere else that .HasValue returns true always.
The way you're checking for null is fine, there must be something else that's setting the field's value.
To find what's setting the field you could right-click it then do find all references, then scan the list for any assignments.
Failing that, you could change it to an explicitly defined property temporarily and set a breakpoint within the set method, then execution will pause whenever the value is set and you can look up the call stack.
I have been using the code,
object amountObject = MySqlDAL.ExecuteQuerySingle(query);
if (amountObject.Equals(System.DBNull.Value))
{
return amount;
}
here in some point am getting an exception "Object reference not set to an instance of an object." from the sentence amountObject.Equals(System.DBNull.Value). Its working fine for some set of data.
What may be the reason? Can any one please help me out?
Try checking the result for null as well..
if (amountObject ==null || amountObject.Equals(System.DBNull.Value))
{
return amount;
}
Presumably MySqlDAL.ExecuteQuerySingle is returning null instead of System.DBNull.Value. It's hard to know whether that's a bug in your expectations or in ExecuteQuerySingle though.
Sometimes the query doesn't return a value, therefore amountObject is null.
Manually run the query with the parameters that make this fail, there's something wrong with your SQL.
Just change:
if (amountObject.Equals(System.DBNull.Value))
{
return amount;
}
to:
if (amountObject != null && amountObject.Equals(System.DBNull.Value))
{
return amount;
}
Have you checked if amountObject is null? It seems that the returned value by MySqlDAL.ExecuteQuerySingle return NULL.
I have a class property that is a list of strings, List.
Sometimes this property is null or if it has been set but the list is empty then count is 0.
However elsewhere in my code I need to check whether this property is set, so currently my code check whether it's null and count is 0 which seems messy.
if(objectA.folders is null)
{
if(objectA.folders.count == 0)
{
// do something
}
}
Any recommendation on how this should be handled?
Maybe I should always initialise the property so that it's never null?
When I have List as a property, I usually have something that looks like the following (this is not a thread safe piece of code):
public class SomeObject
{
private List<string> _myList = null;
public List<string> MyList
{
get
{
if(_myList == null)
_myList = new List<string>();
return _myList;
}
}
}
Your code would then never have to check for null because the Property would be initialized if used. You would then only have to check for the Count.
Right now your code will Always throw a Null Pointer exception, you are checking for Null and if it IS null - you're trying to access an object which does not exist.
If for your application the collection being a null reference never has a different meaning than the collection being empty, then yes, I would say you should always initialize it and this way remove the null checks from the remaining code.
This approach only makes sense if the property setter does not allow to change it to a null reference after initialization.
You have three options (and you need to decide based on your project):
Create a method to check for NullOrNoElements. Pro: Allows both null and no entries. Con: You have to call it everywhere you want to use the property.
Preinitialize with a list. Pro: Thread-save and very easy. Con: will use memory even when not used (depending on how many instances you have this may be a problem)
Lazy initialize Pro: Does only use memory when really used. Con: NOT thread save.
private List<string> lp = null;
public List<string> ListProp
{
get
{
if(lp == null)
lp = new List<string>();
return lp;
}
}
You could always initialize the property so it's an empty List. Then you can just check the count property.
List<String> Folder = Enumerable.Empty<String>();
I once wrote an extension method for ICollection objects that checked if they were null or empty
public static Boolean IsNullOrEmpty<T>(this ICollection<T> collection)
{
return collection == null ? true : collection.Count() == 0;
}
public static Boolean IsPopulated<T>(this ICollection<T> collection)
{
return collection != null ? collection.Count() > 0 : false;
}
You could do this in a single IF
if(objectA.folders is null || objectA.folders.count == 0)
Or you could create a boolean property in the class which checks this status for you and returns a result
public bool objectA.FolderIsNullOrEmpty
{
get { return objectA.folders is null || objectA.folders.count == 0;}
}
If it does not make a difference to your application, I would rather recomend initializing the List to start with.
You could handle this by initializing the object in the constructor. This is usually where this type of thing is done. Although I see nothing wrong with your current code. No point in initializing stuff that doesn't exist yet, it just wastes memory.
Its a good question. I would add a method to objectA FoldersNullOrEmpty() that you can use eg
public virtual FoldersNullOrEmpty()
{
return (folders == null || folders.count == 0)
}
I almost always initialize lists and even make sure they can't be set to null if exposed by any setters. This makes using them much easier.