I have created a matching method which basically takes in a Person
object, makes a call to an address service and then tries to do a match firstly by trying like for like and then if that does not work it concatenates the house name/number with the saon
information (flat 1a etc) to see if that works.
If it does find a match I need to store that matched address in my variable matchingAddress
and then process that further which is what the rest of the method does, I have excluded this for clarity.
Problem
I think I have a problem with my lamda
statement, on the second IF
with the person I am debugging with the if statement is returning true and I am dropping into the assignment code however it is being set to null even though the IF
statement is meant to be checking that it is not null
.
Can anyone explain what is going on here?
private void AttemptMatch(Person person, string username)
{
var postcode = person.Postcode;
List<JsonAddressModel> Addresses = _service.GetAddress(postcode); //returns a list of addresses for that persons postcode
JsonAddressModel matchingAddress = new JsonAddressModel();
//1.) Access the Service and see if theres a straight forward match
if (Addresses.FirstOrDefault(x => x.paon.Trim() == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo) != null)
{
matchingAddress = Addresses.First(x => x.paon.Trim() == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo);
}
//2.) try and combine the paon and saon and see if that matches address line one
if (Addresses.Where(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo) != null)
{
matchingAddress = Addresses.Where(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo).FirstOrDefault();
}
if (matchingAddress != null)
{
//rest of method to complete matching process for matched person
}
else
return;
}
Stop repeating work you've already done 1 , and just remove some of this conditional logic:
//1.) Access the Service and see if theres a straight forward match
//if (Addresses.FirstOrDefault(x => x.paon.Trim() == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo) != null)
//{
matchingAddress = Addresses.FirstOrDefault(x => x.paon.Trim() == person.AddressLineOne &&
x.thorofare.Trim() == person.AddressLineTwo) ??
//}
//2.) try and combine the paon and saon and see if that matches address line one
//if (Addresses.Where(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo) != null)
//{
/*matchingAddress = */
Addresses.Where(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) ==
person.AddressLineOne &&
x.thorofare.Trim() == person.AddressLineTwo).FirstOrDefault();
//}
Your current problem is caused because in the second if
, you're not calling any selection method (like FirstOrDefault
or ToList
, etc) and so what you're checking is whether the query is null rather than any result.
1 At the moment, you run a query merely to determine whether it returns any results, and then you run the query again to actually obtain those results. Then, you potentially (if you'd not got the second if
slightly wrong) do that same trick a second time, and use that to overwrite the previous result to boot, which was the actual result you wanted, I believe. So, instead, we just run one query, and if it returns null, we use ??
to move along and try the second query.
The reason you enter the if
is that you are not calling FirstOrDefault()
inside the condition. What's compared to null
is the return of the Where
method, which is never null
.
You can optimize your code by storing the result of FirstOrDefault
in a temporary variable, and then assigning it only when it's not null
:
var tmp1 = Addresses.FirstOrDefault(x => x.paon.Trim() == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo);
if (tmp1 != null) {
matchingAddress = tmp1;
}
var tmp2 = Addresses.FirstOrDefault(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo);
if (tmp2 != null) {
matchingAddress = tmp2;
}
Try changing this:
Addresses.Where(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo) != null
For
Addresses.Any(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo) != null
And ideally you won't need that if. Your SingleOrDefault should be doing the trick.
Basically the Where never returns null, it just return an empty IEnumerable
never returns null value. You need to check if returned collection is empty.
I suppose the best option is to change "where" with "any"
if (Addresses.Any(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo))
This linq is returning collection, which is always not null. It can be empty but never null.
Try this:
if (Addresses.Any(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo))
{
matchingAddress = Addresses.Where(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo).FirstOrDefault();
}
It will check if there is any matching item.
You can try this in your second if:
if (Addresses.Where(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo).FirstOrDefault() != null) { matchingAddress = Addresses.Where(x => String.Format("{0} {1}", x.paon.Trim(), x.saon.Trim()) == person.AddressLineOne && x.thorofare.Trim() == person.AddressLineTwo).FirstOrDefault(); }
The 'Addresses.Where(filter)' return null is impossible. when all element in IEnumerable<T>
not satisfied the where filter, It would be return empty IEnumerable<T>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.