简体   繁体   中英

LINQ ANY() with First() And FirstOrDefault()

I've written code like this

TotalCashIn = totals != null && totals.Any() ? totals.First().TotalCashIn : null;

And i have been blamed for this code and have told to write like this

TotalCashIn = totals != null ? totals.FirstOrDefault().TotalCashIn : null;

But I am wondering would not I get an exception if totals count would be 0? Do I need also check this with .Any() or .Count() ?

You can use the null-conditional operator to make all of this a lot simpler, assuming that the element type of totals is a reference type:

TotalCashIn = totals?.FirstOrDefault()?.TotalCashIn;

With this:

  • If totals is null, the overall result is null due to the first null-conditonal operator
  • If totals is empty, FirstOrDefault() will return null, so the overall result is null due to the second null-conditional operator
  • Otherwise, the result is the TotalCashIn property of the first element

It depends whether totals is IEnumerable or IQueryable . If it is IQueryable then you can also use following:

TotalCashIn = totals?.Select(t => (int?)t.TotalCashIn).FirstOrDefault();

It would be better as you select only desired field and not all columns in a table.

If totals is a reference type object, then indeed, FirstOrDefault might return null, and thus you can't call TotalCashIn.

If on the other hand totals is a value type, then FirstOrDefault would return an actual value and you could call TotalCashIn. For instance if totals would be a sequence of integers, then FirstOrDefault would return zero (not null!).

If TotalCashIn would be an extension function of int, then if would be perfect to call TotalCashIn after FirstOrDefault:

IEnumerable<int> totals = ...
int firstInt = totals.FirstOrDefault();
var totalCashIn = firstInt.TotalCashIn(); // extension function of int

or in one statement:

var totalCashIn = totals.FirstOrDefault().TotalCashIn();

Whether it is wise to use the null-conditional operator (?.) depends on the definition of your TotalCashIn, especially if your collection has no element at all.

If you'd say: "TotalCashIn represents the amount of money I cashed while ...", then TotalCashIn could have a zero value, but not a null value.

If you want a zero value in case of empty collections, consider to use Select to select the property you want before your FirstOrDefault:

var totalCashIn = totals.Select(item => item.TotalCashIn).FirstOrDefault();

If property TotalCashIn is a value type then this will return zero if your totals collection is empty

Upon your question whether to use Count() or Any(): never use Count() to test if your sequence has any elements unless you are certain the your input sequence is an ICollection. It is really a waste of computing power to access all elements of your sequence if after the first element you would already know there are elements.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM