Possible Null Reference Exception using "as" operator - c#

In the following code:
MyObject objInstance;
private void someEventHandler(object sender, EventArgs e)
{
if (sender == objInstance && (sender as MyObject).SomeBoolProperty)
// Do Something
}
Resharper is warning that sender as MyObject may be a possible NullReferenceException. Is that possible given this code? I'm assuming that if sender == objInstance that (sender as MyObject) won't return null, but this wouldn't be the first time a Resharper message has informed me of a C# behavior/feature I was unaware of.

When you use as, null is returned if the object couldn't be converted (in this case, to MyObject). Therefore, your line (sender as MyObject) has the potential to be null.

This code can definitely cause a NullReferenceException to be thrown. Consider the case where objInstance and sender have the value null. In that case sender == objInstance will be true because null == null and hence the sender as MyObject will also return null and the code will throw on the property access
The best way to write that code would be
var senderObj = sender as MyObject;
if (senderObj != null &&
senderObj == objInstance &&
senderObj.SomeBoolProperty) {
// Do something
}
Unfortunately I don't believe there is a way to significantly simplify this code. There are 3 specific unrelated conditions you are attempting to express. Hence they must all be tested for

In this case you know that sender is really a MyObject. So use a simple cast instead of as:
if (sender == objInstance && ((MyObject)sender).SomeBoolProperty)
Or, even better:
if (sender == objInstance && objInstance.SomeBoolProperty)

The as operator returns null if your cast is not valid. If the Event sender is not of MyObject, (sender as MyObject) == null.
If objInstance is guaranteed to not be null, then your statement will never throw a NullReferenceException. However, it may throw if objInstance is null.
Since you can determine sender == objInstance, just operate on objInstance rather than casting sender, after verifying objInstance != null.

This is because R# isn't always the smartest. Also, you could still get a NullReferenceException if both sender and objInstance are null. Anyways, as you've established their equality, why not just use objInstance?
Try this instead:
if (sender == objInstance && objInstance.SomeBoolProperty)

To get rid of the squiggly:
MyObject objInstance;
private void someEventHandler(object sender, EventArgs e)
{
var myObj = sender as MyObject;
Debug.Assert(myObj != null);
if (sender == objInstance && myObj .SomeBoolProperty)
// Do Something
}
R# comprehends the assertion and will stop warning you. Also, it isn't such a bad practice to liberally insert these debugging assertions. Anytime you are receiving a reference type as an argument of a public method, I would assert that the value is not null, or in some cases throw an exception specifically for receiving a null parameter instead of waiting for the code to fail further down. It gets worse when that null is passed into other methods making it really difficult to know where and when the code will fail.

Related

GetComponent returning "null" instead of null

I'm confused about the return value of GetComponent if the requested component is not attached to the object. According to the Unity documentation, GetComponent should return null. However, what appears to be happening is that GetComponent is returning a "null" object of the requested type, rather than the value null.
In this example, my game object does not have a CircleCollider2D attached to it. When I set a breakpoint on the line CircleCollider2D x = GetComponent<CircleCollider2D>();, I get this result
Why is the returned value not null?
EDIT:
Here's a full screenshot of the code and the values in the debugger.
ANOTHER EDIT:
Could it be that Unity has overloaded the == operator so that GetComponent always returns a object, but the object can have an internal "null" state which returns true when compared to null? I can see the following declarations in the UnityEngine namespace
public static bool operator ==(Object x, Object y);
public static bool operator !=(Object x, Object y);
It seems like GetComponent<T>() doesnt return TRUE null. Instead it returns new T with default values that fires MissingComponentException when using any null field. GetInstanceID() and GetHashCode() work because they only use int m_InstanceID which is set to default 0. Not sure how ToString() works but it probably returns "null" when m_InstanceID == 0.
Proof:
void Start()
{
CircleCollider2D getComponent = GetComponent<CircleCollider2D>();
CircleCollider2D empty = null;
CircleCollider2D newCC = new CircleCollider2D();
Debug.LogFormat("getComponent.GetInstanceID() {0}", getComponent.GetInstanceID());
Debug.LogFormat("newCC.GetInstanceID() {0}", newCC.GetInstanceID());
try
{
Debug.LogFormat("empty.GetInstanceID() {0}", empty.GetInstanceID());
}
catch (System.NullReferenceException e)
{
Debug.Log("empty.GetInstanceID() doesnt work, im true null");
}
try
{
string t = getComponent.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("getComponent fires {0} when any field is null",
e.ToString()));
}
try
{
string t = newCC.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("newCC fires {0} when any field is null",
e.ToString()));
}
}
Results:
getComponent.GetInstanceID() 0
newCC.GetInstanceID() 0
empty.GetInstanceID() doesnt work, im true null
getComponent fires UnityEngine.MissingComponentException
newCC fires System.NullReferenceException
Also:
getComponent.GetHashCode() = 0
getComponent.ToString() = "null"
Why getComponent == null is true? Usually it's just:
`getComponent.GetInstanceID() == otherComponent.GetInstanceID()`
In o == null case it's:
return !(
o.GetCachedPtr() != IntPtr.Zero || (!(o is MonoBehaviour) &&
!(o is ScriptableObject) &&
Object.DoesObjectWithInstanceIDExist(o.GetInstanceID())));
So i guess object with InstanceID = 0 never exists.
Search for decompiled UnityEngine/UnityEngine/Object.cs if u want to know more.
Could it be that Unity has overloaded the == operator
Tldr: Yes.
Why is the returned value not null?
According Custom == operator, should we keep it? :
When a MonoBehaviour has fields, in the editor only, we do not set
those fields to “real null”, but to a “fake null” object.
Why? According that article, basically for two reasons:
On Editor mode: get more contextual information on invocations, so if you have an exception you will be able to know which object was the cause.
Every that comes from UnityEngine.Object are wrapped in a C# object to keep the reference to the Unity C/C++ GameEngine Object. In the editor/code we work with the C# elements but those are just a reference to the 'real' c++ objects. Now, the lifetime of those 'real' c++ objects are handled explicitly (if you destroy something the C++ object it will be destroyed and the allocated memory it will be freed) but the C# object will be completely destroyed when the Garbage Collector decides to free that memory. So you will have a not null C# object pointing to a null C++ object. With this fake null trick you will know that this specific C# object is null because in the C++ side it was destroyed.
This is also important when if you have a singleton and if (sm_Instance == null) is not working as expected, you can use: if (EqualityComparer<T>.Default.Equals(sm_Instance, null)) instad.
Edit: Probably this can be caused if your singleton use generics and your type constrain is class
public class Singleton<T> where T : class {
This will cause to use the == operator of a class object, even when your Singleton is a GameEngine Object. One fix for that? Instead of class you can use UnityEngine.Object, like:
public class Singleton<T> where T : UnityEngine.Object {
Related Thread:
https://forum.unity3d.com/threads/null-check-inconsistency-c.220649/#post-1775701
Ps: If you go to UnityEngine.Object assembly, you will be able to see the overload:
Almost at the end...
if you are still looking for solution this worked for me`
var component = parent.GetChild(i).GetComponent<T>();
if(component != null)
{
if (component.ToString().Equals("null") == false)
{
list.Add(component);
}
}
GetComponent is expected to return object of type 'Component. Hence it is not expected to return "null" rather ~null is expected value. Perhaps this strange behavior should be reported to unity3d,

Error : possible unintended reference comparison to get a value comparison cast the right hand

I have the following code which gives a warning "possible unintended reference comparison; to get a value comparison, cast the right hand side to type string":
// oControl is of type Control
if ((ocontrol.Name == oDataRowView["ConName"].ToString()))
{
//Do stuff
}
else
{
//Do other Stuff
}
I've tried to fix it using each of the following but I still get a warning
if ((ocontrol.Name == Convert.ToString(oDataRowView["ConName"])))
{
//Do stuff
}
else
{
//Do other Stuff
}
if ((ocontrol.Name == (string)oDataRowView["ConName"]))
{
//Do stuff
}
else
{
//Do other Stuff
}
Please could someone explain the reason I still get a warning and the best practice way to deal with this?
These options will work:
if (Equals(ocontrol.Name, oDataRowView["ConName"])) // likely best option
if ((string)ocontrol.Name == oDataRowView["ConName"].ToString()) // assuming neither item is null
if (ocontrol.Name as string == oDataRowView["ConName"] as string) // assuming second item is actually a string

Where to use if(obj == null) When writing API?

I am always confused about when to use if (sth == null). Design of delegate in C# is like this:
//Declaration:
private delegate void OnSthHappened();
//In some place, do:
OnSthHappened += SthHappendCallback;
//When use delegate:
if(OnSthHappened != null)
OnSthHappened();
I really think of judging it is null everytime when use OnSthHappened is unnecessary. I know that in compiler, delegate will become a class to handle the callback. Then why the C# compiler doesn't do the other way like:
//Use the delegate directly:
OnSthHappened();
//In the created-by-compiler class, do the judgement:
//object: instance object, Intptr method: a method pointer
if(method != 0x00) //Null, hide the judgement here
{
Invoke(object, method);
}
I just gave a scene of where to judge null, this is giving me hard choices everytime when I try to write API, to do ==null in caller or called functions? Does anyone could give me some style about where to use ==null judgement?
I know that in compiler, delegate will become a class to handle the callback
Delegate (more precise, MulticastDelegate, because in fact we work with multicast delegates) is a class already. The delegate keyword is just a way to declare a MulticastDelegate-derived type.
Where to use if(obj == null) When writing API?
Shortly, check for null:
in public or protected contacts, if the particular method parameter or return value must not be null. If it is null, throw an exception;
in public, protected or private contracts, when value the value could be null, and you can handle that.
public void Method1(Action action)
{
Contact.Requires<ArgumentNullException>(action != null);
}
public object Method2()
{
Contract.Ensures(Contract.Result<object>() != null);
// code here
}
public void Method2(Action action == null)
{
if (action != null)
action();
}
Do not check for null:
in private contacts, when value must not be null.
private void Method3()
{
var result = Method2();
// In case of result == null, NRE is a best option here.
Console.WriteLine(result.ToString().Length);
}
UPD.
why use different strategies between private and public methods? What is the benefit?
Public or protected surface is unpredictable.
You can't guarantee, that user of your class will provide, for example, valid parameter values. That's why you must check them - this is the way to tell the user, that something is wrong in his code. By delivering understandable exception, you can tell, what is wrong exactly. Note, that user hasn't access to your code, and ArgumentNullException on your method call is much more cleaner, that NullReferenceException inside of your method.
On the other hand, your release code should be clean from extra checks.
If you'll return null from any private method, and then try to access a member of that null value, you'll get NRE during debugging or testing. Then you have to fix error in your code and forget it. If you have fixed the error, there's no reason to keep the null-checking alive. This all doesn't avoid Debug.Assert/Contract.Assert or similar. But: a) those thing should live in debug version of your code; b) they must not be after every line of code, because this reduces code readability; c) often it is enough to catch an exception in debugger/unit test result.

Resting a private variable that should not happen

I have a strange problem I'm checking in my code behind the user if he is active or not with as simple if .. in my Page_Load method as you can see here
private TimeReport paramTR;
private ZevUser zevUser;
protected void Page_Load(object sender, EventArgs e)
{
ZevUser user = ZevUser.GetById(Int32.Parse(Session["SessionId"].ToString()));
if (user == null)
{
this.Response.Redirect("~/About.aspx");
}
this.getParameters();
if (!this.IsPostBack)
{
if (paramTR.ZevUser.Active == 0)
{
this.Response.Redirect("~/TimeReporting/TimeReportPanel.aspx");
}
this.bindData();
}
}
But when I make a go throw to this method I get allays nullreferenceexception why so ever .. but the private ZevUser variable is not null it's full..
I really don't have a clue why is this happing, it would be really cool if someone could explain me this why this is happening
Thanks for help and fast answer
You need to break your code down so you can debug it easier or add logging if you cannot debug this code locally.
Remember that when debugging something, the worse mistake you can make is to make assumptions. Start from the beginning and follow the process through. Don't assume that the problem is something and don't assume that the problem can't be something:
I've included a broken down, more readable version below. You can now add logging around this or easily add breakpoints:
private TimeReport paramTR;
private ZevUser zevUser;
protected void Page_Load(object sender, EventArgs e)
{
this.getParameters();
if (!this.IsPostBack)
{
if ((this.paramTR != null) &&
(this.paramTR.ZevUser != null) &&
(this.paramTR.ZevUser.Active == 0))
{
this.Response.Redirect("~/TimeReporting/TimeReportPanel.aspx");
}
this.bindData();
}
string sessionId = Session["SessionId"] as string;
if (sessionId != null)
{
int session = int32.Parse(sessionId);
ZevUser user = ZevUser.GetById(session);
if (user == null)
{
this.Response.Redirect("~/About.aspx");
}
}
}
Why are you passing the session id to ZevUser.GetById()? I would expect this to take a user id, or for the method to be called something like ZevUser.GetBySessionId(). At the moment it's quite confusing.
This line is causing the issue:
ZevUser user = ZevUser.GetById(Int32.Parse(Session["SessionId"].ToString()));
This is because Session["SessionId"] can be null, and is null in this case.
If you are looking to get the SessionId that is set by ASP.net, then use this.Session.SessionID (source).
If you are storing a value in Session["SessionId"] that you are trying to retrieve, then do a null-check first:
if (Session["SessionId"] != null) { ...
You should consider testing the SessionId variable before using it by doing something like that :
if (!string.IsNullOrEmpty(Session["SessionId"].ToString()))
ZevUser user = ZevUser.GetById(Int32.Parse(Session["SessionId"].ToString()));
The best way to debug your exception is to enable debug when the exception is thrown.
For this, go to Debug>>Exceptions
and then enable first four checkboxes (maybe) and then try debugging the project. You will be halted at the position from where the exception will be thrown.

objects are not null and exception is still raised

Answer: it was in the else code, but I thought there is no reason that code wouldn't point to that line.
Can someone offer an idea how it could be possible that I get "Object reference not set to an instance of an object" on this at Invoke method:
delegate void t(tabdescriptor tab);
internal void AddItem(tabdesciptor tab)
{
if (InvokeRequired)
{
t inv = new t(AddItem);
if (inv != null && tab!= null)
Invoke(inv, tab);
}
else
{
....
}
}
I'm not exactly sure what the actual issue is considering your example cannot be the code that executes, but please try something like this:
internal void AddItem(tabdesciptor tab)
{
if (InvokeRequired)
{
Invoke(new Action<tabdescriptor>(AddItem), tab);
}
else
{
//...
}
}
Also please make sure that it's not actually whatever is in the else part that fails.
If I remember correctly, this exception could be coming from inside the invoked method. If you place a try/catch inside the else of the AddItem method and a breakpoint inside the catch, do you catch the exception?
internal void AddItem(tabdesciptor tab)
{
if (InvokeRequired)
{
t inv = new t(AddItem);
if (inv != null && tab!= null)
Invoke(inv, tab);
}
else
{
try
{
....
}
catch
{
// breakpoint here
}
}
}
It's unclear whether it's a mistake in the given example, or not, but tab is never checked for null, yet it is passed as the argument.
Either it's probably null, or:
Also, inv is checked for null right after creating it (Good in C/C++, but unnecessary in C# as it throws an OutOfMemoryException upon failure), but it is done before checking o for null.

Categories