I have XML as shown below
<NodeName Foo="True" Foobar="False" />
<NodeName Foo="False" Foobar="False" />
<NodeName Foo="True" Foobar="False" />
I am querying this to find NodeName's with a Foo value of 'True' using:
.Where(node => node.Attribute("Foo").Value = "True");
However there is the possibility that the attribute Foo may not exist and this causes an exception.
The question is how do you implement logic to check if the attribute exists and then check for the value if it does exist?
I have tried the following however not sure what goes in the else bracket to return nothing as currently it wont compile with an error of not returning a value on all paths.
.Where(node =>
{
if (node.Attribute("Foo") != null)
{
node.Attribute("Foo").Value == "True";
}
else { }
});
However there is the possibility that the attribute Foo may not exist and this causes an exception.
This is where the explicit conversion from XAttribute (and indeed XElement) to string and a number of other types comes in handy:
.Where(node => (string) node.Attribute("Foo") == "True");
The conversion will return null when there's no such attribute. This is much more convenient than finding the attribute twice - once for presence and once for the value.
Alternatively, you could use the conversion to bool? which will also return null if the attribute is missing, so you need to use the null-coalescing operator to effectively provide a default:
.Where(node => (bool?) node.Attribute("Foo") ?? false);
EDIT: In terms of why your statement-lambda approach doesn't work, you don't have any return statements. This would work, although obviously it's not what I'd recommend:
.Where(node =>
{
if (node.Attribute("Foo") != null)
{
return node.Attribute("Foo").Value == "True";
}
else
{
return false;
}
});
The lambda must return a boolean value to determine whether the node will be in the result set.
Try this:
xml.Where(node => node.Attribute("Foo") != null && node.Attribute("Foo").Value == "True");
just do this
.Where(node => node.Attribute("Foo") == null ? false : node.Attribute("Foo").Value == "True");
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I was wondering what was the most clean and understandable syntax for doing condition checks on nullable bools.
Is the following good or bad coding style? Is there a way to express the condition better/more cleanly?
bool? nullableBool = true;
if (nullableBool ?? false) { ... }
else { ... }
especially the if (nullableBool ?? false) part. I don't like the if (x.HasValue && x.Value) style ...
(not sure whether the question has been asked before ... couldn't find something similar with the search)
I think a lot of people concentrate on the fact that this value is nullable, and don't think about what they actually want :)
bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else { ... } // false or null
Or if you want more options...
bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else if (nullableBool == false) { ... } // false
else { ... } // null
(nullableBool == true) will never return true if the bool? is null :P
How about using GetValueOrDefault, which is pretty self-explaining and allows to use whatever default you want:
if (nullableBool.GetValueOrDefault(false)) {
}
You may not like it, but personally I find
if (x.HasValue && x.Value)
the most readable. It makes it clear you are working with a nullable type and it makes it clear you are first checking whether the nullable type has a value before acting on it conditionally.
If you take your version and replace the variable with x also it reads:
if (x ?? false)
Is that as clear? Is it obvious x is a nullable type? I'll let you decide.
Another way is to use constant pattern matching:
if (nullableBool is true) {}
if (nullableBool is false) {}
if (nullableBool is null) {}
Unlike the operator ==, when reading the code, this will distinguish the nullable type check from ordinary "code with a smell".
If you want to treat a null as false, then I would say that the most succinct way to do that is to use the null coalesce operator (??), as you describe:
if (nullableBool ?? false) { ... }
Just think of bool? as having 3 values, then things get easier:
if (someNullableBool == true) // only if true
if (someNullableBool == false) // only if false
if (someNullableBool == null) // only if null
Actually I think that (nullableBool ?? false) is a legitimate option especially when you are trying to evaluate a nullable bool in linq.
For example:
array.Select(v => v.nullableBool ?? false)
(from v in array where v.nullableBool ?? false)
Is cleaner in my opinion as opposed to:
array.Select(v => v.nullableBool.HasValue ? v.nullableBool.Value : false)
(from v in array where v.nullableBool.HasValue ? v.nullableBool.Value : false)
Use extensions.
public static class NullableMixin {
public static bool IsTrue(this System.Nullable<bool> val) {
return val == true;
}
public static bool IsFalse(this System.Nullable<bool> val) {
return val == false;
}
public static bool IsNull(this System.Nullable<bool> val) {
return val == null;
}
public static bool IsNotNull(this System.Nullable<bool> val) {
return val.HasValue;
}
}
Nullable<bool> value = null;
if(value.IsTrue()) {
// do something with it
}
Lets check how the comparison with null is defined:
static void Main()
{
Console.WriteLine($"null != null => {null != null}");
Console.WriteLine($"null == null => {null == null}");
Console.WriteLine($"null != true => {null != true}");
Console.WriteLine($"null == true => {null == true}");
Console.WriteLine($"null != false => {null != false}");
Console.WriteLine($"null == false => {null == false}");
}
and the results are:
null != null => False
null == null => True
null != true => True
null == true => False
null != false => True
null == false => False
So you can safely use:
// check if null or false
if (nullable != true) ...
// check if null or true
if (nullable != false) ...
// check if true or false
if (nullable != null) ...
If you only want to test for true against null/false, One I've just used and reads quite well is
bool? someCondition = null
if (someCondition.Equals(true))
...
I think its up to you. I certainly think the .HasValue approach is more readable, especially with developers not familiar with the ?? syntax.
The other point of a nullable boolean type is that it is tristate, so you may want to do something else when it is just null, and not default to false.
Given enum
public enum PublishMode { Edit, View }
you can do it like here
void MyMethod(PublishMode? mode)
{
var publishMode = mode ?? PublishMode.Edit;
//or
if (mode?? PublishMode.Edit == someValue)
....
}
If you're in a situation where you don't have control over whether part of the condition is checking a nullable value, you can always try the following:
if( someInt == 6 && someNullableBool == null ? false : (bool)someNullableBool){
//perform your actions if true
}
I know it's not exactly a purist approach putting a ternary in an if statement but it does resolve the issue cleanly.
This is, of course, a manual way of saying GetValueOrDefault(false)
I am working on WPF application. In which I am trying to fetch records from list as per required condition. But when there is no any record found then it's giving me object reference not found error.
var recordList = _outputVariables.ToList().Where(X => X.symbolName == _symbolName).ToList();
if (recordList != null)
{
//more coding...
}
so as shown in code when _outputVariables have no any record match as per _symbolName then it's giving error of Object reference not set to an instance of an object.' and X was null.. So how can I handle this issue ? please help for it.
Use the null-conditional operator that was introduced in C#6 (and don't call ToList() more than once):
var recordList = _outputVariables?.Where(X => X?.symbolName == _symbolName).ToList();
if (recordList != null)
{
//more coding...
}
var recordList = _outputVariables.ToList().Where(X => X.symbolName == _symbolName).ToList();
You currently loop through _outputVariables, but if it's null this will give an error, because null does not have a .ToList(). So you should add a ? after your _outputVariables, so it will return null instead of an exception when it's null.
Same goes for X. If X is null and you try to get the property symbolName, you will get an error, because null doesn't have a property called symbolName. So you want to add a ? here too. So it will return null instead of an exception.
Leaving you with: var recordList = _outputVariables?.ToList().Where(X => X?.symbolName == _symbolName).ToList();
You can use like below as well
if (_outputVariables != null && _outputVariables.Count > 0)
{
var recordList = _outputVariables.Where(X => X != null && !string.IsNullOrEmpty(X.symbolName) && X.symbolName == _symbolName);
}
You can try this
if(_outputVariables!=null)
{
var recordList = _outputVariables.Where(X => X.symbolName ==_symbolName).ToList();
}
if (recordList != null)
{
//more coding...
}
I have the following:
var tagId = "5288";
source.Where(p => p.GetPropertyValue<IEnumerable<string>>("picker").Contains(tagId));
This returns the error System.ArgumentNullException: Value cannot be null.
So some of the returned results, does not contain a picker value. How would I check for this, in the above statement?
It is a Umbraco Multinode treepicker that is the "picker" value.
If I understand correctly, the result of GetPropertyValue can be null if the picker value is not found. In that case, you can use a null conditional operator:
source.Where(p => p.GetPropertyValue<IEnumerable<string>>("picker")?.Contains(tagId) == true);
Note the ?. after GetPropertyValue. If that method returns null then it's not true, so those will not be included in the filtered objects.
Use this:
source.Where(p =>
{
var pickerVal = p.GetPropertyValue<IEnumerable<string>>("picker");
if (pickerVal == null)
return false;
return pickerVal.Contains(tagId);
});
or more condensed:
source.Where(p =>
{
var pickerVal = p.GetPropertyValue<IEnumerable<string>>("picker");
return (pickerVal != null) && pickerVal.Contains(tagId);
});
if statement to check the value of an attribute doesn't work.
if (element.Elements(ns + "list").Where(x => x.Attribute("name").Value == "myProject") != null)
Is there other way to check if the value of an attribute exists?
you can use firstordefault
var element = element.Elements(ns + "list").Where(x => x.Attribute == "myProject");
// return if null
if(element == null) return;
// do your stuff
Sorry for messy indentation as I'm typing on mobile :)
Here is my code:
string displayName = Dictionary.FirstOrDefault(x => x.Value.ID == long.Parse(options.ID)).Value.DisplayName;
The code works fine if x.Value.ID matches options.ID. However, I get a NullReferenceException if it doesn't.
FirstOrDefault returns the default value of a type if no item matches the predicate. For reference types that is null. Thats the reason for the exception.
So you just have to check for null first:
string displayName = null;
var keyValue = Dictionary
.FirstOrDefault(x => x.Value.ID == long.Parse(options.ID));
if(keyValue != null)
{
displayName = keyValue.Value.DisplayName;
}
But what is the key of the dictionary if you are searching in the values? A Dictionary<tKey,TValue> is used to find a value by the key. Maybe you should refactor it.
Another option is to provide a default value with DefaultIfEmpty:
string displayName = Dictionary
.Where(kv => kv.Value.ID == long.Parse(options.ID))
.Select(kv => kv.Value.DisplayName) // not a problem even if no item matches
.DefaultIfEmpty("--Option unknown--") // or no argument -> null
.First(); // cannot cause an exception
You can use a combination of other LINQ methods to handle not matching condition:
var res = dictionary.Where(x => x.Value.ID == someID)
.Select(x => x.Value.DisplayName)
.DefaultIfEmpty("Unknown")
.First();
Simply use the question mark trick for null checks:
string displayName = Dictionary.FirstOrDefault(x => x.Value.ID == long.Parse(options.ID))?.Value.DisplayName ?? "DEFINE A DEFAULT DISPLAY NAME HERE";
That is because FirstOrDefaultcan return null causing your following .Value to cause the exception. You need to change it to something like:
var myThing = things.FirstOrDefault(t => t.Id == idToFind);
if(myThing == null)
return; // we failed to find what we wanted
var displayName = myThing.DisplayName;
To add to the solutions, here is a LINQ statement that might help
Utilities.DIMENSION_MemTbl.Where(a => a.DIMENSION_ID == format.ContentBrief.DimensionID).Select(a=>a.DIMENSION1).DefaultIfEmpty("").FirstOrDefault();
The result will be an empty string if the result of the query is a null..
This answer is for those of us who need a visual write up (like me :)
In the code screenshot below, a NullReferenceException will be thrown, the root cause is the ReferenceIdentification_02 property.
When debugging, we see that the orderLine.REF array, I am querying does not include a matching object whose ReferenceIdentificationQualifier_01 value == "RU", so at that point FirstOrDefault() return value is NULL
to prevent the NullReferenceException, I do a FirstOrDefault() on the orderLine.REF array first. If the returned value is not null then I retrieve the value.
i assume you are working with nullable datatypes, you can do something like this:
var t = things.Where(x => x!=null && x.Value.ID == long.Parse(options.ID)).FirstOrDefault();
var res = t == null ? "" : t.Value;
you can use with 'Where' statement with FirstOrDefault().
like this.
var modelItem = _dbcontext.ModelName.Where(n => n.NewsTagId == newsTag.Id).FirstOrDefault();
It returns first item if does not match query.
It is better practice to check the NULL after query.
if(modelItem == null)
{
return "Not Found."
}
else
{
// continue process
}