Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ Lambda求和空_C#_Linq_Lambda - Fatal编程技术网

C# LINQ Lambda求和空

C# LINQ Lambda求和空,c#,linq,lambda,C#,Linq,Lambda,我使用LINQ to objects对两个对象中的值进行求和,并返回一个包含求和总数的单一版本的对象 我遇到的问题是LINQ sum函数将空值求和为零(0)。如果我有一个值是“15”,另一个值是“null”,那么总和应该是“15”。但我希望,如果第一个值是“null”,第二个值是“null”,那么总和也应该是“null”。然而,它告诉我总和是“0” 我怎样才能让它像我期望的那样工作?如果至少有一个值,我希望它返回一个值;如果没有值,则返回“null” 现在了解一些代码: virtual publ

我使用LINQ to objects对两个对象中的值进行求和,并返回一个包含求和总数的单一版本的对象

我遇到的问题是LINQ sum函数将空值求和为零(0)。如果我有一个值是“15”,另一个值是“null”,那么总和应该是“15”。但我希望,如果第一个值是“null”,第二个值是“null”,那么总和也应该是“null”。然而,它告诉我总和是“0”

我怎样才能让它像我期望的那样工作?如果至少有一个值,我希望它返回一个值;如果没有值,则返回“null”

现在了解一些代码:

virtual public IStatSplit Totals
{
  get
  {
    var cSplit = _splits.Where(s => s.Split == SplitType.COMBINED).SingleOrDefault();

    if( cSplit != null )
    { return cSplit; }

    cSplit = _splits.Where( s => s.Split != SplitType.COMBINED )
                    .GroupBy( g => 1 == 1 ).Select( x => new StatSplit
    {
      AB = (uint?)x.Sum( q => q.AB ),
      CI = (uint?)x.Sum( q => q.CI ),
      B2 = (uint?)x.Sum( q => q.B2 ),
      B3 = (uint?)x.Sum( q => q.B3 ),
      GDP = (uint?)x.Sum( q => q.GDP ),
      H = (uint?)x.Sum( q => q.H ),
      HB = (uint?)x.Sum( q => q.HB ),
      HR = (uint?)x.Sum( q => q.HR ),
      RBI = (uint?)x.Sum( q => q.RBI ),
      IBB = (uint?)x.Sum( q => q.IBB ),
      SF = (uint?)x.Sum( q => q.SF ),
      SH = (uint?)x.Sum( q => q.SH ),
      SO = (uint?)x.Sum( q => q.SO ),
      BB = (uint?)x.Sum( q => q.BB ),
      Split = SplitType.COMBINED
    } ).SingleOrDefault();

    return cSplit;
  }
}
以下是无法通过单元测试的测试数据:

[TestMethod]
public void PitchingTotals()
{
  var splits = GetSplits();
  var pitching = new Base.Pitching();
  pitching.Splits = splits;

  var expected = GetTotalSplit();
  var result = pitching.Totals;

  // result.RBI = 0
  // expected.RBI = null
  // this fails because the "0" is not expected

  Assert.AreEqual( expected, result );
}

private List<IStatSplit> GetSplits()
{
  var lhSplit = new Base.StatSplit
  {
    AB = 442,
    H = 97,
    B2 = 14,
    B3 = 0,
    HR = 6,
    BB = 28,
    HB = 6,
    SF = 1,
    SH = 5,
    SO = 73,
    GDP = 7,
    IBB = 4,
    CI = 0,
    RBI = null,
    Split = Enumerations.SplitType.VS_LEFT
  };

  var rhSplit = new Base.StatSplit
  {
    AB = 633,
    H = 101,
    B2 = 9,
    B3 = 0,
    HR = 5,
    BB = 34,
    HB = 1,
    SF = 1,
    SH = 10,
    SO = 195,
    GDP = 11,
    IBB = 2,
    CI = 0,
    RBI = null,
    Split = Enumerations.SplitType.VS_RIGHT
  };

  List<IStatSplit> splits = new List<IStatSplit>();
  splits.Add( lhSplit );
  splits.Add( rhSplit );

  return splits;
}

private IStatSplit GetTotalSplit()
{
  var split = new Base.StatSplit
  {
    AB = 1075,
    H = 198,
    B2 = 23,
    B3 = 0,
    HR = 11,
    BB = 62,
    HB = 7,
    SF = 2,
    SH = 15,
    SO = 268,
    GDP = 18,
    IBB = 6,
    CI = 0,
    RBI = null,
    Split = Enumerations.SplitType.COMBINED
  };

  return split;
}
[TestMethod]
公共无效投手总数()
{
var splits=GetSplits();
var pitching=新的基底。pitching();
俯仰。劈裂=劈裂;
应为var=GetTotalSplit();
var结果=俯仰。总计;
//result.RBI=0
//应为0.RBI=null
//此操作失败,因为不需要“0”
断言.AreEqual(预期、结果);
}
私有列表GetSplits()
{
var lhSplit=new Base.StatSplit
{
AB=442,
H=97,
B2=14,
B3=0,
HR=6,
BB=28,
HB=6,
SF=1,
SH=5,
SO=73,
GDP=7,
IBB=4,
CI=0,
RBI=null,
Split=枚举数.SplitType.VS_左
};
var rhSplit=new Base.StatSplit
{
AB=633,
H=101,
B2=9,
B3=0,
HR=5,
BB=34,
HB=1,
SF=1,
SH=10,
SO=195,
GDP=11,
IBB=2,
CI=0,
RBI=null,
Split=Enumerations.SplitType.VS_RIGHT
};
列表拆分=新列表();
拆分。添加(lhSplit);
拆分。添加(rhSplit);
返回分裂;
}
私有IStatSplit GetTotalSplit()
{
var split=new Base.StatSplit
{
AB=1075,
H=198,
B2=23,
B3=0,
HR=11,
BB=62,
HB=7,
SF=2,
SH=15,
SO=268,
GDP=18,
IBB=6,
CI=0,
RBI=null,
Split=枚举数.SplitType.COMBINED
};
收益分割;
}
您应该编写自己的“SumOrNull”扩展方法,在您描述的情况下(null+null=null),该方法可以返回“uint?”。现有的Linq Sum方法只返回不可为空的数字


您可以使用


这将从一个
null
uint?
值开始,并遍历每个项目。如果当前
sum
和值
currentItem.AB
均为
null
,则下一个
sum
将继续为
null
。如果其中一个不是
null
,则添加它们,如果其中一个是
null
,则使用默认值,
uint
的值为0。

根据Juharr的回答,我首先尝试了以下方法:

cSplit = _splits.Where( s => s.Split != SplitType.COMBINED )
    .GroupBy( g => 1 == 1 ).Select( x => new StatSplit
    {
      AB = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.AB.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.AB.GetValueOrDefault() ),
      CI = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.CI.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.CI.GetValueOrDefault() ),
      B2 = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.B2.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.B2.GetValueOrDefault() ),
      B3 = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.B3.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.B3.GetValueOrDefault() ),
      GDP = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.GDP.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.GDP.GetValueOrDefault() ),
      H = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.H.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.H.GetValueOrDefault() ),
      HB = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.HB.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.HB.GetValueOrDefault() ),
      HR = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.HR.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.HR.GetValueOrDefault() ),
      RBI = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.RBI.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.RBI.GetValueOrDefault() ),
      IBB = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.IBB.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.IBB.GetValueOrDefault() ),
      SF = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.SF.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.SF.GetValueOrDefault() ),
      SH = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.SH.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.SH.GetValueOrDefault() ),
      SO = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.SO.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.SO.GetValueOrDefault() ),
      BB = x.Aggregate( (uint?)null, ( sum, item ) => !sum.HasValue && !item.BB.HasValue ?
            (uint?)null : sum.GetValueOrDefault() + item.BB.GetValueOrDefault() ),
      Split = SplitType.COMBINED
    } ).SingleOrDefault();
这很管用,但我觉得很难看。我做了一些改进,得出了以下结论:

cSplit = _splits.Aggregate( new StatSplit() { Split = SplitType.COMBINED },
    ( sum, item ) =>
    {
      sum.AB = !sum.AB.HasValue && !item.AB.HasValue ? (uint?)null : sum.AB.GetValueOrDefault() + item.AB.GetValueOrDefault();
      sum.CI = !sum.CI.HasValue && !item.CI.HasValue ? (uint?)null : sum.CI.GetValueOrDefault() + item.CI.GetValueOrDefault();
      sum.B2 = !sum.B2.HasValue && !item.B2.HasValue ? (uint?)null : sum.B2.GetValueOrDefault() + item.B2.GetValueOrDefault();
      sum.B3 = !sum.B3.HasValue && !item.B3.HasValue ? (uint?)null : sum.B3.GetValueOrDefault() + item.B3.GetValueOrDefault();
      sum.GDP = !sum.GDP.HasValue && !item.GDP.HasValue ? (uint?)null : sum.GDP.GetValueOrDefault() + item.GDP.GetValueOrDefault();
      sum.H = !sum.H.HasValue && !item.H.HasValue ? (uint?)null : sum.H.GetValueOrDefault() + item.H.GetValueOrDefault();
      sum.HB = !sum.HB.HasValue && !item.HB.HasValue ? (uint?)null : sum.HB.GetValueOrDefault() + item.HB.GetValueOrDefault();
      sum.HR = !sum.HR.HasValue && !item.HR.HasValue ? (uint?)null : sum.HR.GetValueOrDefault() + item.HR.GetValueOrDefault();
      sum.RBI = !sum.RBI.HasValue && !item.RBI.HasValue ? (uint?)null : sum.RBI.GetValueOrDefault() + item.RBI.GetValueOrDefault();
      sum.IBB = !sum.IBB.HasValue && !item.IBB.HasValue ? (uint?)null : sum.IBB.GetValueOrDefault() + item.IBB.GetValueOrDefault();
      sum.SF = !sum.SF.HasValue && !item.SF.HasValue ? (uint?)null : sum.SF.GetValueOrDefault() + item.SF.GetValueOrDefault();
      sum.SH = !sum.SH.HasValue && !item.SH.HasValue ? (uint?)null : sum.SH.GetValueOrDefault() + item.SH.GetValueOrDefault();
      sum.SO = !sum.SO.HasValue && !item.SO.HasValue ? (uint?)null : sum.SO.GetValueOrDefault() + item.SO.GetValueOrDefault();
      sum.BB = !sum.BB.HasValue && !item.BB.HasValue ? (uint?)null : sum.BB.GetValueOrDefault() + item.BB.GetValueOrDefault();
      return sum;
    } );

第一个运行了大约12毫秒,列表中只有两个项目。改进后的第二个在大约9毫秒内运行,列表中只有两项。我选择第二个条目,因为它更高效,看起来更干净,更容易理解。感谢朱哈尔朝着正确的方向努力

事实并非如此。在您引用的同一个链接中,它显示了Sum的大量重载,这些重载将返回可为null的数据类型。它甚至声明,“如果源不包含元素,则此方法返回零。”LOL,它还声明,“结果不包含null值。”我不知道如果返回类型从未打算返回null,为什么返回类型将为null。@ELMOJO我假设它返回null,因为它将为空集合返回null,但在这种情况下它也返回0。我想他们只是想保持返回类型与求和的类型相同。让我试试这个,然后再给你回复。
cSplit = _splits.Aggregate( new StatSplit() { Split = SplitType.COMBINED },
    ( sum, item ) =>
    {
      sum.AB = !sum.AB.HasValue && !item.AB.HasValue ? (uint?)null : sum.AB.GetValueOrDefault() + item.AB.GetValueOrDefault();
      sum.CI = !sum.CI.HasValue && !item.CI.HasValue ? (uint?)null : sum.CI.GetValueOrDefault() + item.CI.GetValueOrDefault();
      sum.B2 = !sum.B2.HasValue && !item.B2.HasValue ? (uint?)null : sum.B2.GetValueOrDefault() + item.B2.GetValueOrDefault();
      sum.B3 = !sum.B3.HasValue && !item.B3.HasValue ? (uint?)null : sum.B3.GetValueOrDefault() + item.B3.GetValueOrDefault();
      sum.GDP = !sum.GDP.HasValue && !item.GDP.HasValue ? (uint?)null : sum.GDP.GetValueOrDefault() + item.GDP.GetValueOrDefault();
      sum.H = !sum.H.HasValue && !item.H.HasValue ? (uint?)null : sum.H.GetValueOrDefault() + item.H.GetValueOrDefault();
      sum.HB = !sum.HB.HasValue && !item.HB.HasValue ? (uint?)null : sum.HB.GetValueOrDefault() + item.HB.GetValueOrDefault();
      sum.HR = !sum.HR.HasValue && !item.HR.HasValue ? (uint?)null : sum.HR.GetValueOrDefault() + item.HR.GetValueOrDefault();
      sum.RBI = !sum.RBI.HasValue && !item.RBI.HasValue ? (uint?)null : sum.RBI.GetValueOrDefault() + item.RBI.GetValueOrDefault();
      sum.IBB = !sum.IBB.HasValue && !item.IBB.HasValue ? (uint?)null : sum.IBB.GetValueOrDefault() + item.IBB.GetValueOrDefault();
      sum.SF = !sum.SF.HasValue && !item.SF.HasValue ? (uint?)null : sum.SF.GetValueOrDefault() + item.SF.GetValueOrDefault();
      sum.SH = !sum.SH.HasValue && !item.SH.HasValue ? (uint?)null : sum.SH.GetValueOrDefault() + item.SH.GetValueOrDefault();
      sum.SO = !sum.SO.HasValue && !item.SO.HasValue ? (uint?)null : sum.SO.GetValueOrDefault() + item.SO.GetValueOrDefault();
      sum.BB = !sum.BB.HasValue && !item.BB.HasValue ? (uint?)null : sum.BB.GetValueOrDefault() + item.BB.GetValueOrDefault();
      return sum;
    } );