This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
enter image description here
code:
CogFindCircleLastRunRecordConstants.BestFitCircle;
CogFindCircleTool_.Run();
if ((CogFindCircleTool_.Results.GetCircle() != null) && (CogFindCircleTool_.Results.GetCircle().Visible == true))
{
cogRecordDisplay1.Record = CogFindCircleTool_.CreateLastRunRecord().SubRecords["InputImage"];
This error is because .Results is null, yet you're trying to call the GetCircle() method on it.
One way to handle this is to use the null-conditional operator (?.), which returns null if the left hand side is null, otherwise continues with the method or property on the right hand side:
// If Results is null, the call to GetCircle will not happen, and the result will be null
// Not needed on the second condition, since '&&' would return 'false' right away
if ((CogFindCircleTool_.Results?.GetCircle() != null) &&
(CogFindCircleTool_.Results.GetCircle().Visible == true))
You could shorten your code even further by adding another .? when accessing the Visible property, and then we don't need to explicitly check for .GetCircle() != null first.
Below, if Results is null or GetCircle returns null, the expression will fail (because null != true), otherwise the condition Visible == true will be evaluated:
if (CogFindCircleTool_.Results?.GetCircle()?.Visible == true)
In the comments you stated that you have a line like this inside the if statement:
Label.SetXYText(CogFindCircleTool_.Results.GetCircle().CenterX,
CogFindCircleTool_.Results.GetCircle().CenterY, "(" +
Math.Round(CogFindCircleTool_.Results.GetCircle().CenterX, 3).ToString() +
"," + Math.Round(CogFindCircleTool_.Results.GetCircle().CenterY, 3).ToString() + ")");
One thing to improve performance is to capture the result fo the GetCircle() method once rather than calling it over and over again, which takes extra processing cycles. This will also make the code shorter and more readable. You can also use string interpolation instead of concatenation to shorten the code a little more.
You also mentioned that you were still getting a null reference exception on the inner line, which could only mean that Label is null (from what I can tell). If so, we could use the ?. operator when calling the SetXYText method:
// Capture the result of GetCircle() once
var circle = CogFindCircleTool_?.Results?.GetCircle();
if (circle?.Visible == true)
{
Label?.SetXYText(circle.CenterX, circle.CenterY,
$"({Math.Round(circle.CenterX, 3)},{Math.Round(circle.CenterY, 3)})");
}
Note that the code above will not do anything if something is null. If you want to do something else if circle is null or Label is null, then you should explicitly check that rather than use the ?. operator:
if (circle == null)
{
// do something if circle is null
}
else if (circle.Visible == true)
{
if (Label == null)
{
// do something if Label is null
}
else
{
Label.SetXYText(circle.CenterX, circle.CenterY,
$"({Math.Round(circle.CenterX, 3)},{Math.Round(circle.CenterY, 3)})");
}
}
Related
I have a simple function in my Unity game code where I am looking for a "work spot" - an empty place for my NPCs to do some task.
This code works perfectly well 99.999% of the time, but throws a NULL REFERENCE EXCEPTION very occasionally and I can't for the life of me figure out where. I have tried to catch every possible place where something could be unassigned and can't find it. There must be some edge case I am missing, or something in my code that misbehaves under some strange circumstances.
So my code is flawed and I don't understand where. Help me improve it:
public Transform[] workSpots;
public Transform findAvailableWorkSpot() {
if (workSpots == null || workSpots.Length == 0) return null; // sometimes we have no work spots
int i=0;
while (i<10) {
Transform spot = workSpots[Random.Range(0, workSpots.Length)];
if (spot != null && spot.childCount == 0) {
return spot;
}
i++;
}
// couldn't find one randomly, let's just iterate over them:
foreach (Transform spot in workSpots) {
if (spot != null && spot.childCount == 0) {
return spot;
}
}
Debug.LogError("could not find free workspot on "+gameObject.name);
return null;
}
Logic:
first, try up to 10 times to get a free random work spot. I parent the NPC to the work spot when he is working there, so spot.childCount == 0 is true if the spot has no NPC on it right now.
if that fails, then I just iterate over all of them and pick the first free one.
it is ok to return null here, the calling code will handle that
The Diagnostic backend tells me that 2-4 times a day someone experiences a Null Reference Exception in this function, but diagnostics doesn't tell me the line number and I've never seen it locally. I'm looking at it again and again and I can't spot where it could be. Maybe something more fundamental is wrong with my code?
Additional Information:
workspots is initialized in Awake() and is never again changed, so I am sure that the test at the beginning of the function works and it's not possible that it goes to null while the function is running.
This is not directly an answer to where exactly the exception comes from.
But if you are open to using Linq you can simplyfy your code a lot!
I would simply use
using System.Linq;
...
public Transform[] workSpots;
public bool TryFindAvailableWorkSpot(out Transform freeSpot)
{
// First heck this component even is alive
if (!this || workSpots == null || workSpots.Length == 0)
{
freeSpot = null;
return false;
}
// First "Where" filters out only those spots that exist and have no children
// then "OrderBy" randomizes these results
// then we take the first one or null if there isn't any
freeSpot = workSpots.Where(spot => spot && spot.childCount == 0).OrderBy(spot => Random.value).FirstOrDefault();
// use the implicit bool operator for checking if we have found a valid reference
return freeSpot;
}
and then instead of using
var spot = yourClass.findAvailableWorkSpot();
and having to again check for null and potential exceptions you would rather simply do the check in the same line using e.g.
if(yourClass.TryFindAvailableWorkSpot(out var spot))
{
... Do someting with spot
}
else
{
Debug.LogError("could not find free workspot");
}
See
Linq Where
Linq OrderBy
Random.value
Linq FirstOrDefault
Unityengine.Object implicit bool operator
I don't think you are looking at the right place where the exception happened. The way you've written the code it's just not possible for workSpots to be null or empty.
The only places where I can see a null reference exception happening is if you are trying to access workSpots[index] -> and that returns a Transform object that is null and you try using it (but in your code you are prepared for that).
Maybe the places where you use that particular method do not check if the Transform that you are returning is null before trying to access it.
If your code is well written and you don't believe it then the null reference exception is probably caused by gameObject.name when trying to log an error. If it isn't that then I have no idea honestly.
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 2 years ago.
So i know this is a common problem but the solutions ive seen are not working for me, Sorry if i havent given enough information. Line 31 is where the error happens according to unity. Here is the code
using UnityEngine;
using UnityEngine.UI;
public class Scoring : MonoBehaviour
public Text Score1;
private int scorePoint1;
// Update is called once per frame
void Start()
{
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.name == ("WallLeft"))
{
scorePoint1 += 1;
Debug.Log("ScorePoint");
}
}
void Update()
{
Score1 = GetComponent<Text>();
Score1.text = "" + scorePoint1.ToString();
}
}
I have tried multiple answers and it seems like everything is connected UI wise (I have tested it with different stuff and it worked) its just this is not working. Im almost it is the scorePoint1 variable that is causing it as i have done it with other variables and it worked but as soon as i switched it out for that it no longer worked. Thanks for the help!
Quick edit: i did a null check as told to on the lines and i confirmed Score1.text = "" + scorePoint1.ToString() ?? string.Empty; this line is what is causing it. Still unsure how to fix it but atleast i know this for certain
From your code any of these expressions can be the cause of the problem:
if (col.gameObject.name == ("WallLeft"))
Score1.text = "" + scorePoint1.ToString();
Debug your code and you will find there's a null check needed in one of those 3 places.
Also as a separate note:
"" + scorePoint1.ToString();
This will potentially allocate 3 strings in memory. First an empty string and then the scorePoint1 as string and then third string where the 2 values are concatenated together.
This is very bad for performance especially in a game or in a loop. If you want a string that is never null, do this instead. That will be 3 times more memory efficient:
scorePoint1?.ToString() ?? string.Empty;
Ad1:
Score1.text = "" + scorePoint1.ToString() ?? string.Empty;
The ?? is null coalescing.
= If left side is null, use right side instead.
But that is not your problem, you can't call ToString() on a null object.
In my example I use the ?. null-conditional.
= If left side is null, don't call the method/property after ?. and return null.
This is what you want, it will never fail even if there's null.
Score1.text = scorePoint1?.ToString() ?? string.Empty;
So you can see if scorePoint1 is null, ToString() is never called and prevents your error. The expression scorePoint1?.ToString() returns null, which is handled by the null coalesce and gets replaced by string.Empty.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I don't know before this asked or not, but I am confuse in below of code block.
CODE 1
if (String.IsNullOrEmpty(control.Text.Trim()))
{
// Code to execute
}
CODE 2
if (control.Text.Trim() == "")
{
// Code to execute
}
CODE 3
if (control.Text.Trim() == null)
{
// Code to execute
}
CODE 4
if (control.Text.Trim() == string.Empty)
{
// Code to execute
}
According to me all are working to me.
I just feeling wonder that what is the different in between in this 4 code block.
Let's start from primitives:
The first block checks if the string control.Text.Trim() is null or String.Empty.
The second block checks if the string control.Text.Trim() is "".
The third block checks if the string control.Text.Trim() is null.
The fourth block checks if the string control.Text.Trim() is String.Empty; this is exactly the same as the second block: "" equals String.Empty.
Fine, that's easy to understand. However, note that String.Trim() will never return null. Thus, the first block is equivalent to control.Text.Trim() == String.Empty. This is same as the second block and the fourth block, again because "" equals String.Empty. The third block will never be hit, ever.
Thus, the first, second and fourth blocks are equivalent to checking if control.Trim the empty string and the third block is useless and impossible to satisfy. Be careful, if control is null or control.Text is null you will hit an exception. Thus, you should strongly consider using `String.IsNullOrWhiteSpace and replacing everything with:
if(control != null && String.IsNullOrWhiteSpace(control.Text)) {
// code to execute
}
(unless you have some sort of guarantee that control is not null, in which case leave off the first part of the if).
More proper would be:
if (String.IsNullOrWhiteSpace(control.Text))
{
// Code to execute
}
that way you avoid null reference exception.
All your examples have the same bug, they will throw exception if variable is null.
You should also see diference between string.empty ("") and null, those are not the same things. Code 4 and code 2 are the same but both would throw if Text is null.
control.Text.Trim() is never going to be null
control might be
control.Text might be
in which case all three versions will blow chunks...
private static bool validControl(Control argControl)
{
return (argControl != null) && (argControl.Text != null) && (argControl.Text.Trim() != ""));
}
if (validControl(control))
{
// code to execute
}
maybe
I deal with this type of issue all the time and was wondering if you had any slick elegant work arounds:
if(myObject != null && myObject.myProperty != myValue){
//do something
}else{
//do something else
}
If I run this logic, I get null reference when myObject is null so I end up doing:
if(myObject != null){
if(myObject.myProperty != myValue){
//do something
}else{
//do something else
}
}else{
//do something else
}
So I end up having redundant code on my "do something else" how do you guys handle this?
The first check for null means that the second condition won't be evaluated if that isn't met - when using logical AND (&&) - so I suggest your null reference exception comes from elsewhere, not that latter condition.
There is no "elegant" way to deal with this - two ways of sharing the code of "do something else" are really of varying degree of non-elegance:
You can put the "do something else" code into a function, or
Define a flag before entering the if to say if additional processing is needed, and act on the flag upon exit from the if statement.
The first solution is self-explanatory; the second solution looks like this:
var processed = false;
if(myObject != null) {
if(myObject.myProperty != myValue){
//do something
processed = true;
}
// do more stuff knowing that myObject is not null
}
if (!processed) {
// do something else
}
your first statement is perfectly valid.
if(myObject != null && myObject.MyProperty != myValue)
What this will do is it will evaluate myObject != null first, and since there's a && to the right of it, If it's false, it doesn't even need to evaluate the other clause.
If you just copy and paste the code you pasted here, I think you'll find that it runs successfully
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Shortcut for “null if object is null, or object.member if object is not null”
I wish there were a way to make this type of test simpler in C#:
if (foo != null &&
foo.bar != null &&
foo.bar.baz != null &&
foo.bar.baz.bat != null)
{
var bat = foo.bar.baz.bat;
bat.cat = 5;
bat.dog = 6;
}
One possible feature that would support this is if statements that supported new variable declarations, e.g.
if (foo != null &&
(var bar = foo.bar) != null &&
(var baz = bar.baz) != null &&
(var bat = baz.bat) != null)
{
bat.cat = 5;
bat.dog = 6;
}
The gains may not be obvious here, since the proposed solution is actually longer in this example. But with longer names it would really pay off.
Is there any better way to do this? Any chance of a suggestion like this actually making it into a future version of the language (calling Eric Lippert, come in)?
This is a fairly frequently requested feature, and as a result this question has now been asked several times on StackOverflow. See
Shortcut for "null if object is null, or object.member if object is not null"
for some thoughts on it.
Good question, but bad intentions. Your code is going to ignore the Law of Demeter
I usually just move the expression in the if-statement to its own method at the bottom of the file:
if (CheckBat(foo))
{
var bat = foo.bar.baz.bat;
bat.cat = 5;
bat.dog = 6;
}
... snip ...
private bool CheckBat(MyFoo foo)
{
return foo != null &&
foo.bar != null &&
foo.bar.baz != null &&
foo.bar.baz.bat != null;
}