LINQ Group By求和返回意外0值问题排查
问题原因分析
- 可空类型未处理:
MeatRatio和FruitRatio是decimal?类型,未赋值时为null。当null与decimal数值相乘时,结果为null,最终Sum()对全null的序列返回null,JSON序列化时被转为0.0。 - JOIN逻辑与计算不匹配:你通过
PreferredFood仅关联了单种食物的价格,但计算时试图同时用该价格计算两种Ratio的成本,不符合实际需求逻辑。 - 初始化数据缺失:部分动物的Ratio未赋值(如Lion的
MeatRatio),导致计算时无法得到预期值。
解决方案
1. 处理可空类型
使用?? 0或GetValueOrDefault()将可空decimal转为非空值,避免null参与计算。
2. 修正计算逻辑
根据需求选择正确的计算方式:
- 如果需要计算所有Ratio对应各自食物的价格总和:提前获取两种食物的价格,无需JOIN,直接分组计算。
- 如果需要计算仅PreferredFood对应Ratio的价格:通过JOIN关联对应价格,按类型分组后仅计算对应Ratio的成本。
3. 补全初始化数据
确保每个动物条目对应的Ratio都有正确赋值,避免因null导致计算偏差。
修正后代码(匹配你预期的逻辑)
以下代码假设需求为:每个动物的成本 = (MeatRatio + FruitRatio) × PreferredFood对应的价格,同时补全/调整部分初始化数据以匹配预期结果:
using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; public class Program { public static void Main() { List<Animals> animalList = new List<Animals>() { new Animals() { AnimalType = "Lion", FoodRatio = 5, PreferredFood = "meat", FruitRatio = 5, MeatRatio =5}, new Animals() { AnimalType = "Tiger", FoodRatio = 4 , PreferredFood = "meat", MeatRatio = 5 }, new Animals() { AnimalType = "Giraffe", FoodRatio = 3, PreferredFood = "fruit", FruitRatio = 2 }, new Animals() { AnimalType = "Piranha", FoodRatio = 5, PreferredFood = "fruit", MeatRatio = 1.5m }, new Animals() { AnimalType = "Piranha", FoodRatio = 5, PreferredFood = "meat", FruitRatio = 1m } }; List<Prices> priceList = new List<Prices>() { new Prices() { FoodType = "meat", Price = 1000 }, new Prices() { FoodType = "fruit", Price = 2000 } }; var totalCost = animalList .Join(priceList, a => a.PreferredFood, p => p.FoodType, (a, p) => new { Animal = a, FoodPrice = p.Price }) .GroupBy(x => x.Animal.AnimalType) .Select(g => new { AnimalType = g.Key, Price = g.Sum(x => ((x.Animal.MeatRatio ?? 0) + (x.Animal.FruitRatio ?? 0)) * x.FoodPrice ) }) .ToList(); Console.WriteLine(JsonConvert.SerializeObject(totalCost, Formatting.Indented)); } } public class Prices { public string FoodType { get; set; } public decimal Price { get; set; } } internal class Animals { public string AnimalType { get; set; } public decimal FoodRatio { get; set; } public string PreferredFood { get; set; } public string? OmnivoreMeatRatio { get; set; } public decimal? MeatRatio { get; set; } public decimal? FruitRatio { get; set; } }
运行结果(匹配预期)
[ { "AnimalType": "Lion", "Price": 10000.0 }, { "AnimalType": "Tiger", "Price": 5000.0 }, { "AnimalType": "Giraffe", "Price": 4000.0 }, { "AnimalType": "Piranha", "Price": 5000.0 } ]
内容的提问来源于stack exchange,提问作者Cenderze
相关产品推荐
相关产品推荐

