Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
223 views
in Technique[技术] by (71.8m points)

c# - Why don't the values from my linq queries appear immediately?

I have the following block of linq queries to calculate some values for a report.

var items = (from trans in calclabordb.Sales_Transactions                
             select trans).SelectMany(st => st.Sales_TransactionLineItems).Where(stli => stli.TypeID == typeID);

decimal test = items.Where(stli => stli.Inventory_Item is Base).Sum(stli => (decimal?)stli.Inventory_Item.IntExtraServiceAmount) ?? 0;
decimal test2 = items.Where(stli => stli.Inventory_Item is Extra).Sum(stli => (decimal?)stli.ItemPrice) ?? 0;
decimal test3 = test + test2;
current.ExtraSales = items.Where(stli => stli.Inventory_Item is Base).Sum(stli => (decimal?)stli.Inventory_Item.IntExtraServiceAmount) ?? 0 +
    items.Where(stli => stli.Inventory_Item is Extra).Sum(stli => (decimal?)stli.ItemPrice) ?? 0;

I've stepped through the code in a debugger and I've noticed some oddities. After assigning into test its value is 0. After assigning into test2 test2 == 0 and test == 11.31 after assigning into test3 test == 11.31 test2 == 11.28 and test3 == 22.59 after assigning into ExtraSales ExtraSales == 11.31. The value in ExtraSales when this is all complete should be 22.59. What's going on here?

EDIT: I've added additional lines after the assignment into ExtraSales but the value does not change.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The answers that say that this is a deferred execution problem are wrong. It is an operator precedence problem.

Get rid of all that completely irrelevant and impossible-to-read code in there. It is all red herring. The relevant repro is:

decimal? d1 = 11.31m;
decimal? d2 = 11.28m;
decimal test1 = d1 ?? 0m;
decimal test2 = d2 ?? 0m;
decimal test3 = test1 + test2;
decimal test4 = d1 ?? 0m + d2 ?? 0m;

What is the meaning of the final line? Does it mean the same thing as the line before it?

No, it does not. The addition operator is higher precedence than the null coalescing operator, so this is

decimal test4 = d1 ?? (0m + d2) ?? 0m;

The code you wrote means "produce the value of d1 if d1 is not null. If d1 is null and 0m + d2 is not null then produce the value of 0m + d2. If 0m + d2 is null then produce the value 0m."

(You might not have known that the ?? operator has this pleasant chaining property. In general, a ?? b ?? c ?? d ?? e gives you the first non-null value of a, b, c or d, and e if they are otherwise all null. You can make the chain as long as you like. It's quite an elegant little operator.)

Since d1 is not null, we produce its value and test4 is assigned the value of d1.

You probably meant to say:

decimal test4 = (d1 ?? 0m) + (d2 ?? 0m);

If you mean "d1 or d2 could be null, and if either is, then treat the null one as zero". So 12 + 2 is 14, 12 + null is 12, null + null is 0

If you mean "either d1 and d2 could be null, and if either is null then I want zero", that's

  decimal test4 = (d1 + d2) ?? 0m;

So 12 + 2 is 14, 12 + null is 0, null + null is 0

I note that if you had formatted your code so that the relevant text was on the screen, you probably wouldn't have gotten five or so incorrect answers posted first. Try to format your code so that all of it is on the screen; you'll get better answers if you do.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...