c# - linq左连接中的NullReferenceException,如何处理空值?
问题描述
我正在尝试将树列表与 linq 中的左连接一起加入,但我在 select 语句中得到了 System.NullReferenceException。
打印出 dataCost 以 { ParrentLineNo = 0, Cost = 230 } 的形式给出数据,dataPrice 给出 { ParrentLineNo = 0, Price = 500 }
我希望 dataJoined 以 {lineNo,Cost,Price} 的形式保存数据
我认为问题是 lineNo = 9。它不包含在 dataCost 中,所以我希望 dataJoined 中的 x.cost 为空。
我试过 x.Cost ?? line.Cost,但这不适用于双打。
希望你能帮助med解决这个问题。
这是我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqGroup
{
class Line
{
public int LineNo { get; set; }
public int ParrentLineNo { get; set; }
public double Cost { get; set; }
public double Price { get; set; }
public string IsItem { get; set; }
public string VareType { get; set; }
static public List<Line> Data()
{
Line line9 = new() { LineNo = 9, ParrentLineNo = 9, Cost = 99, Price = 999, IsItem = "No", VareType = "Vare" };
Line line1 = new() { LineNo = 0, ParrentLineNo = 0, Cost = 100, Price = 500, IsItem = "No", VareType = "Stykliste" };
Line line2 = new() { LineNo = 1, ParrentLineNo = 0, Cost = 110, Price = 0, IsItem = "Yes", VareType = "Vare" };
Line line3 = new() { LineNo = 2, ParrentLineNo = 0, Cost = 120, Price = 0, IsItem = "Yes", VareType = "Vare" };
Line line4 = new() { LineNo = 3, ParrentLineNo = 3, Cost = 130, Price = 1000, IsItem = "No", VareType = "Stykliste" };
Line line5 = new() { LineNo = 4, ParrentLineNo = 3, Cost = 140, Price = 0, IsItem = "Yes", VareType = "Vare" };
Line line6 = new() { LineNo = 5, ParrentLineNo = 3, Cost = 150, Price = 0, IsItem = "Yes", VareType = "Vare" };
List<Line> lines = new() { line9, line1, line2, line3, line4, line5, line6 };
return lines;
}
}
class Program
{
static public void Main()
{
var lines = Line.Data();
// Build pricedata
var dataPrice = from line in lines
where line.IsItem == "No"
group line by line.ParrentLineNo into Group
select new
{
ParrentLineNo = Group.Key,
Price = Group.Sum(x => x.Price)
};
// Build costdata
var dataCost = from line in lines
where line.IsItem == "Yes"
group line by line.ParrentLineNo into Group
select new
{
ParrentLineNo = Group.Key,
Cost = Group.Sum(x => x.Cost)
};
// Join it all
var dataJoined = from line in lines
join x in dataCost on line.ParrentLineNo equals x.ParrentLineNo into mma
from x in mma.DefaultIfEmpty()
join y in dataPrice on line.ParrentLineNo equals y.ParrentLineNo into pma
from y in pma.DefaultIfEmpty()
select new
{
line.LineNo,
x.Cost,
y.Price
};
// Then display
foreach (var d in dataJoined)
{
Console.WriteLine(d);
}
}
}
}
解决方案
问题的原因是你有这样的行,它分配DefaultIfEmpty
给一个变量:
from line in lines
join x in dataCost on line.ParrentLineNo equals x.ParrentLineNo into mma
from x in mma.DefaultIfEmpty()
由于DefaultIfEmpty
如果结果为空,将返回类型的默认值,并且知道所有类的默认值为null
,那么我们以后不能这样做:
select new
{
line.LineNo,
x.Cost, // Can't do this when 'x' is 'null'
y.Price
};
因为x
is null
,我们无法访问它的Cost
属性。
解决此问题的一种方法是在这种情况下仅使用null
该匿名类型属性的值:
select new
{
line.LineNo,
x?.Cost, // The '?.' operator returns 'null' if the left side is 'null'
y?.Price
};
请注意,我们应该y
以相同的方式处理,因为对于某些数据集也可能如此null
,并且我们会有相同的例外。
我在你的一个评论中看到你说,
“如何获得第 9 行的输出,例如 { LineNo = 0, Cost = null, Price = 500 }”
要实际输出"null"
(作为字符串),我们需要接管类的输出方式,而不是依赖于 default Property = value
,因为null
在默认实现中只产生一个空格。相反,我们可以这样做:
// The '??' operator returns the right side if the left side is null
foreach (var d in dataJoined)
{
Console.WriteLine($"{{LineNo = {d.LineNo}, " +
$"Cost = {d.Cost?.ToString() ?? "null"}, " +
$"Price = {d.Price?.ToString() ?? "null"}}}");
}
另一种解决方案是x
通过不使用以下方法来忽略 null 的情况(从我们的结果中删除它们)DefaultIfEmpty
:
var dataJoined = from line in lines
join x in dataCost on line.ParrentLineNo equals x.ParrentLineNo into mma
from x in mma
join y in dataPrice on line.ParrentLineNo equals y.ParrentLineNo into pma
from y in pma
select new
{
line.LineNo,
x.Cost,
y.Price
};
推荐阅读
- azure-devops - Azure DevOps 服务器如何使某些组可用于所有项目
- c# - authorize.net sdk controller.execute() 抛出错误 生成 XML 文档时出错
- php - 根据数量划分项目
- javascript - 滚动页面时更改元素的高度将元素移动到视口之外
- python - python代码比较句子对,并查看它们是否在文本文件中的相同或不同块中
- macos - macOS 下未设置 Qt DevicePixelRatio
- python - 带条件的 if 语句
- python - 如何运行 ParlAI Blender 聊天机器人?
- node.js - NestJS 拦截器 - 处理 .pipe() 内的错误
- html - Emmet 已停止在 Visual Studio 2019 和 VS code 中工作