So I've got a collection of struct
s (it's actually a WCF datacontract but I'm presuming this has no bearing here).
List<OptionalExtra> OptionalExtras;
OptionalExtra
is a struct
.
public partial struct OptionalExtra
Now I'm running the below statement:
OptionalExtra multiOptExtra = OptionalExtras.Where(w => w.Code == optExtra.Code).FirstOrDefault(); if (multiOptExtra != null) { }
Now this won't compile:
the operator != cannot be applied to opperands of type OptionalExtra and
'<null>'
After a little googling I realised it's because OptionalExtra
is a struct
. Which I believe is not nullable unless defined as a nullable type?
So my question is, if my where
statement returns no results what will be the outcome of the FirstOrDefault
call? Will it thrown an exception?
Incidently this should never happen but better safe than sorry.
FirstOrDefault<TSource>(IEnumerable<TSource>, TSource) Returns the first element of a sequence, or a specified default value if the sequence contains no elements.
The major difference between First and FirstOrDefault is that First() will throw an exception if there is no result data for the supplied criteria whereas FirstOrDefault() returns a default value (null) if there is no result data.
FirstOrDefault. It returns first specific element from a collection of elements if one or more than one match found for that element. A default value is returned, if no match is found for that element in the collection.
Use First() when you are sure that a query must return a record, and use FirstOrDefault() when you are not sure whether it will return a record or not.
If your collection is empty, FirstOrDefault
will return default(OptionalExtras)
. The default value of a struct is the struct with all its values in turn default initialized (i.e. zero, null, etc.).
If you assume that there will be an element and your code doesn't work with an empty collection, Use First()
instead, since that will throw an exception when your collection is empty. It's generally better to fail fast than to return wrong data.
If you cannot assume that there will be an element, but also cannot deal with struct default initialization, you might make the structs in the collection a nullable value type, for example as follows:
OptionalExtras .Where(w => w.Code == optExtra.Code) .Cast<OptionalExtra?>() .FirstOrDefault();
This way you can get a null return even for a struct. The key idea here is to extend the set of possible values to include something other than an OptionalExtra
to allow detection of an empty list. If you don't like nullables, you could instead use a Maybe<>
implementation (not a .NET builtin), or use an empty-or-singleton list (e.g. .Take(1).ToArray()
. However, a nullable struct is likely your best bet.
.FirstOrDefault<T>()
returns default(T)
if the sequence is empty.First()
instead if you assume the list is non-empty..FirstOrDefault<T>()
when you cannot assume the list is non-empty.As others have said, the result of your code when no elements match will be:
default( OptionalExtra )
If you want a null returned, you can cast your list to OptionalExtra?
OptionalExtra? multiOptExtra = OptionalExtras.Cast<OptionalExtra?>().Where( ...
You can then test for null
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With