c# Object reference not set to an instance of an object - c#

I'm trying to work out if something does not exist in the table. I'm telling it to see if the UserInfo contains information for user.
UserInfo Character = db.UserInfoes.SingleOrDefault(a => a.Username == user);
if (Character.Username == null || Character.Username.Length == 0)
{
//do stuff
}
But I get an error on the if statement.
Object reference not set to an instance of an object.

It seems that the db.UserInfoes.SingleOrDefault(a => a.Username == user) expression returned null because it didn't find any matching records that satisfy the filter criteria.
so:
UserInfo Character = db.UserInfoes.SingleOrDefault(a => a.Username == user);
if (Character == null || Character.Username == null || Character.Username.Length == 0)
{
//do stuff
}

You wrote in the comments that you know that db.UserInfoes.SingleOrDefault(a => a.Username == user) returned null. Hence, Character is null and you need to check this case separately:
if (Character == null || // this line is new
Character.Username == null ||
Character.Username.Length == 0)
{
//do stuff
}

Since you say the error occurs on the if statement, Character is null. You need to add a check for if (Character == null).

First you should check whether Character is null, then later you should check for remaining in Character.
if(Character != null)
{
if(Character.Username == null || Character.Username.Lenght == 0)
{
//Do Stuff
}
}
EDIT:
or simply you can check only the Character, like
if(Character == null)
{
//Do Stuff
}

If you are getting an error on the if statement, then it is likely that your search:-
UserInfo Character = db.UserInfoes.SingleOrDefault(a => a.Username == user);
Has not found any record matching where Username equals user. When that happens, the value of Character is null.
Your issue is that you are trying to call a property on something that doesn't exist. You need to perform a check to ensure that Character is not null before calling any of its members.
if ( Character != null )
{
// Can now safely call properties on the Character object
}
else
{
// Take the appropriate action for circumstances where we can't
// find a user by username
}

You need to add a test on Character to know if it's null. If that's the case, you'll have the exception you mentionned.
So just do this :
if(Character != null)
{
//Your code can now safely call the Properties/Methods/etcetc...
}

Related

LINQ .Where .Max and Writing to File

I have a program which writes its output to log files to folders in the following format:
Car7 Lap1 00-00-21-5290000
Everything is working fine, but I want to append a # to the filename of the fastest lap time for each car. In order to do so, I placed the following LINQ query inside my car object to act on the List property of Car:
public List<Lap> Laps { get; set; } = new List<Lap>();
public TimeSpan FastestLap => Laps.Where(lap => lap.Number is not null and not 0).Min(lap => lap.LapTime);
I'm using the .Where clause as laps can sometimes be null or 0, and when I write to disk things initially appear to be working:
Car8 Lap39 00-01-07-8900000#
However, only 8 cars get written to disk as opposed to the full field of 20 cars. If I remove only the .Where part of my property above, all the cars and car folders write properly, except the Lap 0 files are typically marked as the fastest lap (which makes sense since they contain incomplete times).
My writing to disk method looks like this:
foreach (var car in carList)
{
Directory.CreateDirectory(#$"{outputPath}\{logFileName}\Car{car.Number}");
foreach (var lap in car.Laps)
{
using TextWriter tw = new StreamWriter(#$"{outputPath}\{logFileName}\Car{car.Number}\Car{car.Number} Lap{lap.Number} {lap.LapTime.ToString().Replace(":", "-").Replace(".", "-")}{(lap.LapTime == car.FastestLap ? "#" : "")}.csv");
WriteCsvHeader(tw);
foreach (var telemetryRecord in lap.UniqueTelemetryRecords)
{
WriteCsvLine(tw, lap, telemetryRecord);
}
}
}
Is there a way to prevent this from happening so that all cars and car folders get written to disk?
In this case, use a getter to perform a bit more advanced logic when retrieving the value.
Replace this line:
public TimeSpan FastestLap => Laps.Where(lap => lap.Number is not null and not 0).Min(lap => lap.LapTime);
With this:
public TimeSpan FastestLap
{
get
{
if(Laps.Where(lap => lap.Number is not null and not 0).Count() > 0)
return Laps.Where(lap => lap.Number is not null and not 0).Min(lap => lap.LapTime);
else
return Laps.Min(lap => lap.LapTime);
}
}
This is essentially saying that if any non zero laps exist, get the lowest value. Otherwise, it'll just return the zero value.
One option would be to implement IComparable<T> on your class:
public class Lap : IComparable<Lap>
{
public int CompareTo(Lap other)
{
//if both have nulls or zero they are equal
if((this.Number == null || this.Number == 0) && (other == null || other.Number == null || other.Number == 0) return 0;
// If other is null or the other.Number is null or zero this instance is first in sort order
if (other == null || other.Number == null || other.Number == 0) return -1;
//if this instance has null or zero for the number and other doesn't this instance comes after other
if((this.Number == null || this.Number == 0) && other != null && other.Number != null && other.Number != 0) return 1;
//Comparison depends on this.LapTime to other.LapTime
return LapTime.CompareTo(other.LapTime);
}
......
}
Then you could just call .Sort() on the List<Lap> and your first item in the List will be your fastest lap that is not null or zero. Append the # to the first item in the list and you don't need an extra method in your class.

Complex if statement never gets executed

I have this long if statement that is checking for multiple things. It never seems to execute the code in the curly brackets though.
It is checking two objects.
"currentEngineObject" is the object as it exists in the database.
"engineList" is the object that is passed into this method.
So I am trying to check to make sure that the SizeId is not empty and also has a value for both objects.
If they both have values, but they are not the same value, I want to set the "SizeId" of engineList to the "SizeId" value that is in "currentEngineObject".
But even with test data, it never gets through the large if statement I have.
So I am wondering if there is a problem with my logic? Like should I be using "Or" instead of "And"?
Here is my if block:
if ((currentEngineObject.SizeId.HasValue && currentEngineObject.SizeId.Value != Guid.Empty)
&& (engineList.SizeId.HasValue && engineList.SizeId.Value != Guid.Empty)
&& (currentEngineObject.SizeId.Value != engineList.SizeId.Value))
{
engineList.SizeId = currentEngineObject.SizeId.Value;
}
Thanks!
Try this:
if ((currentEngineObject.SizeId.HasValue && currentEngineObject.SizeId.Value != Guid.Empty)
&& (engineList.SizeId.HasValue && engineList.SizeId.Value != Guid.Empty)
&& !currentEngineObject.SizeId.Equals( engineList.SizeId)) ////Use equals
{
engineList.SizeId = currentEngineObject.SizeId;
}

Null value in linq where clause

I'm having an issue where I want to return results where something matches and I get an error if one of the properties I'm trying to match is null.
if (!string.IsNullOrEmpty(searchString))
{
Infos = Infos.Where(
x =>
x.FirstName.ToLower().Contains(searchString) ||
x.LastName.ToLower().Contains(searchString) ||
x.ContractNum.ToLower().Contains(searchString) ||
x.VIN.ToLower().Contains(searchString) ||
x.Claim.InitiatedBy.ToLower().Contains(searchString)
).ToList();
}
If ContractNum or VIN, for example, are null then it throws an error. I'm not sure how to check if one of these are null inside of a linq query.
You can add explicit null checks:
Infos = Infos.Where(
x =>
(x.FirstName != null && x.FirstName.ToLower().Contains(searchString)) ||
(x.LastName != null && x.LastName.ToLower().Contains(searchString)) ||
(x.ContractNum != null && x.ContractNum.ToLower().Contains(searchString)) ||
(x.VIN != null && x.VIN.ToLower().Contains(searchString)) ||
(x.Claim != null && x.Claim.InitiatedBy != null && x.Claim.InitiatedBy.ToLower().Contains(searchString))
).ToList();
You have multiple options, first is to do an explicit check against null and the other option is to use Null propagation operator.
x.FirstName != null && x.FirstName.ToLower().Contains(searchString)
or
x.FirstName?.ToLower()?.Contains(searchString) == true
But I would suggest you to use IndexOf instead of Contains for case
insensitive comparison.
something like:
x.FirstName?.IndexOf(searchString, StringComparison.CurrentCultureIgnoreCase) >= 0)
Checking the property is null or empty before comparing it it's the only way I know
if (!string.IsNullOrEmpty(searchString))
{
Infos = Infos.Where(
x =>
(!String.IsNullOrEmpty(x.FirstName) && x.FirstName.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.LastName) && x.LastName.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.ContractNum) && x.ContractNum.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.VIN) && x.VIN.ToLowerInvariant().Contains(searchString)) ||
(x.Claim != null && !String.IsNullOrEmpty(x.Claim.InitiatedBy) && x.Claim.InitiatedBy.ToLowerInvariant().Contains(searchString))
).ToList();
}
EXTRA: I added a check on the Claim property to make sure it's not null when looking at InitiatedBy
EXTRA 2: Using the build in function IsNullOrEmpty to compare string to "" and nullso the code is clearer.
Extra 3: Used of ToLowerInvariant (https://msdn.microsoft.com/en-us/library/system.string.tolowerinvariant(v=vs.110).aspx) so the lowering action will act the same no matter of the culture.
You could use ?? to replace it with a acceptable value.
(x.ContractNum??"").ToLower()
I would use the null conditional operator ?, this will however, return a nullable bool? so you will need to handle that appropriately.
Some examples on how to do this:
x?.FirstName?.ToLower().Contains(searchString) == true;
x?.FirstName?.ToLower().Contains(searchString) ?? false;
An alternative method to keep the comparison logic in one place to use a sub collection of the properties and check on those:
Infos = Infos.Where(i=>
new[] {i.FirstName,i.LastName,i.ContractNum /*etc*/}
.Any(w=> w?.ToLower().Contains(searchString) ?? false))
.ToList();
(It does read out all properties, but that shouldn't cost much performance and gains much maintainability )

Variable Declaration inside an IF C#

take a look at the following code :
if( down == null || down.GetFace() != Face.None || down.GetFace() != Face.Partial )
{
// I called GetFace() two times
// How can i avoid to call it two times, and still putting inside that if
}
Thank you!
To be more maintainable and expressive first separate the null check as exceptional case
then get the result to a variable and check it.
if(down == null)
// Some exceptional case .. return or throw exception
var result = down.GetFace();
if(result == Face.None || result != Face.Parial)
// Do your code here
Refactor to a method:
private bool IsFaceNoneOrPartial(Down down)
{
var face = down.GetFace();
return face != Face.None || face != Face.Partial;
}
// Your code is now:
if( down == null || IsFaceNoneOrPartial(down))
{
}

more short code about if statement

i wanted to try the following code:
//all arrays are List<T> type.
if (m.terms[0] != null && m.terms[0].labels != null && m.terms[0].labels[0].title == "Part-of-speech")
{
result = true;
}
but it occured runtime error occasionly in following situation
i. m.terms == null
ii. m.terms != null, but m.terms[0] does not intialized.
iii. m.terms != null, and m.terms[0] has been exist but
m.terms[0].label does not initialized.
...
so i did modify it to like this:
if (m.terms[0] != null)
{
if (m.terms[0].labels != null)
{
if (m.terms[0].labels[0].title == "Part-of-speech") { result = true; }
}
}
is it the best way?
&& is a short circuiting operator, so the first way you wrote it and the second way will be functionally equivalent.
if (a && b && c)
{
// work
}
b will only be evaluated if a returns true. (Same goes for c).
In your code, checking m.terms[0].labels will not be a problem because you would have short-circuited out of the expression if m.terms[0] had been null.
To completely cover yourself, you'd want to possibly add checks for m and m.terms, however.
m != null && m.terms != null && m.terms.Count > 0 && m.terms[0] != null ...
As it evaluates from left to right, it will break on the first condition that doesn't pass and the rest will go unchecked.
int index = 0;
int labelIndex = 0;
string titleToCheck = "Part-of-speech";
if (m != null && m.terms != null && m.terms.Count > index)// or m.Length...
{
if (m.terms[index] != null && m.terms[index].labels != null &&
m.terms[index].labels.Count > labelIndex)
{
if (m.terms[index].labels[labelIndex].title == titleToCheck)
{
result = true;
}
}
}
This is all about readability. C# uses Short-circuit evaluation so in functionality there is no difference.
try this
if (m!=null && m.terms!= null && m.terms[0].labels!=null && m.terms[0].labels[0].title!=null && m.terms[0].labels[0].title == "Part-of-speech")
Yes, it would be better to split off each null check into a separate if statement.
The reason is that the second and third conditions require the first to not be null. If the first is null, then the second and third conditions will in turn throw errors because their parent is null yet is trying to be accessed.

Categories

Resources