gpt4 book ai didi

c# - 如何用 LinQ 对自定义对象求和?

转载 作者:行者123 更新时间:2023-11-30 14:24:13 24 4
gpt4 key购买 nike

首先,我按照本教程创建了我的 Money 对象:https://www.codeproject.com/articles/837791/money-pattern

Money totalItems = _invoice.InvoiceDetails
.Sum(y => y.Amount); // Amount is of type Money

我在 y.Amount 上遇到编译异常:

Cannot implicitly convert type 'Money' to 'long?' Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type

我做错了什么?

这是我的货币类:

public class Money
{
public decimal Amount { get; private set; }
public CurrencyCode Currency { get; private set; }

#region Constructors
public Money() { }
public Money(Money amount)
{
this.Amount = amount.Amount;
this.Currency = amount.Currency;
}
public Money(decimal amount, CurrencyCode currencyCode)
{
this.Amount = amount;
this.Currency = currencyCode;
}
public Money(int amount, CurrencyCode currency)
: this(Convert.ToDecimal(amount), currency)
{
}
public Money(double amount, CurrencyCode currency)
: this(Convert.ToDecimal(amount), currency)
{
}
#endregion

#region Comprasion operators
public static bool operator ==(Money var1, Money var2)
{
if ((object)var1 == null || (object)var2 == null)
return false;

if (var1.Currency != var2.Currency) return false;
return var1.Amount == var2.Amount;
}


public static bool operator !=(Money var1, Money var2)
{
return !(var1 == var2);
}

public static bool operator >(Money var1, Money var2)
{
if (var1.Currency != var2.Currency)
throw new InvalidOperationException("Comprasion between different currencies is not allowed.");

return var1.Amount > var2.Amount;
}

public static bool operator <(Money var1, Money var2)
{
if (var1 == var2) return false;

return !(var1 > var2);
}

public static bool operator <=(Money var1, Money var2)
{
if (var1 < var2 || var1 == var2) return true;

return false;
}

public static bool operator >=(Money var1, Money var2)
{
if (var1 > var2 || var1 == var2) return true;

return false;
}
#endregion

#region Ariphmetical operations
public static Money operator +(Money var1, Money var2)
{
if (var1.Currency != var2.Currency)
{
throw new InvalidCastException("Calculation is using different currencies!");
}

return new Money(var1.Amount + var2.Amount, var1.Currency);
}

public static Money operator -(Money var1, Money var2)
{
if (var1.Currency != var2.Currency)
{
throw new InvalidCastException("Calculation is using different currencies!");
}

return new Money(var1.Amount - var2.Amount, var1.Currency);
}

public static Money operator *(Money var1, Money var2)
{
if (var1.Currency != var2.Currency)
{
throw new InvalidCastException("Calculation is using different currencies!");
}

return new Money(var1.Amount * var2.Amount, var1.Currency);
}

public static Money operator /(Money var1, Money var2)
{
if (var1.Currency != var2.Currency)
{
throw new InvalidCastException("Calculation is using different currencies!");
}

return new Money(var1.Amount / var2.Amount, var1.Currency);
}

public static Money operator *(decimal var1, Money var2)
{
return new Money(var1 * var2.Amount, var2.Currency);
}

public static Money operator *(Money var1, decimal var2)
{
return new Money(var1.Amount * var2, var1.Currency);
}

public static Money operator /(decimal var1, Money var2)
{
return new Money(var1 / var2.Amount, var2.Currency);
}

public static Money operator /(Money var1, decimal var2)
{
return new Money(var1.Amount / var2, var1.Currency);
}

public static Money operator *(int var1, Money var2)
{
return new Money(var1 * var2.Amount, var2.Currency);
}

public static Money operator *(Money var1, int var2)
{
return new Money(var1.Amount * var2, var1.Currency);
}

public static Money operator /(int var1, Money var2)
{
return new Money(var1 / var2.Amount, var2.Currency);
}

public static Money operator /(Money var1, int var2)
{
return new Money(var1.Amount / var2, var1.Currency);
}

public static Money operator *(long var1, Money var2)
{
return new Money(var1 * var2.Amount, var2.Currency);
}

public static Money operator *(Money var1, long var2)
{
return new Money(var1.Amount * var2, var1.Currency);
}

public static Money operator /(long var1, Money var2)
{
return new Money(var1 / var2.Amount, var2.Currency);
}

public static Money operator /(Money var1, long var2)
{
return new Money(var1.Amount / var2, var1.Currency);
}
#endregion

public override bool Equals(object obj)
{
if (obj == null) return false;

Money money = obj as Money;
return (this.Amount == money.Amount && this.Currency == money.Currency);
}

public bool Equals(Money money)
{
if ((object)money == null) return false;

return (this.Amount == money.Amount && this.Currency == money.Currency);
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public override string ToString()
{
return this.Amount.ToString();
}
#endregion

最佳答案

据推测,InvoiceDetails 是一组包含 public Money Amount 属性的类,例如:

public class InvoiceDetail
{
public Money Amount { get; set; }
}

在这种情况下,您可以使用 Enumerable.Aggregate()求和:

var sum = InvoiceDetails.Aggregate(new Money(0, InvoiceDetails.First().Amount.Currency), (s, d) => s + d.Amount);

要摆脱略显丑陋的 new Money(0, InvoiceDetails.First().Amount.Currency) 表达式,您可能需要引入一个特殊的单例 Money.Empty 不含货币,可以添加到任何类型的货币中。或者修改静态运算符以接受 Moneynull 值并执行:

var sum = InvoiceDetails.Aggregate((Money)null, (s, d) => s + d.Amount);

或者,引入中间的 Select() 可能会使表达式更清晰:

var sum = InvoiceDetails.Select(d => d.Amount).Aggregate((s, a) => s + a);

Enumerable.Sum() 的原因不起作用的是它是为一组固定的可枚举算术类型定义的。对于引入了算术运算符重载的任意类型,没有 Sum(),因为对于这种情况没有通用接口(interface)或类型推断。 (请参阅 Is there a constraint that restricts my generic method to numeric types? ,答案是 "no" 。)当然,您可以添加自己的 Enumerable.Sum() 版本,它支持提供自己的算法的类型,请参见例如this answer开始的地方。

关于c# - 如何用 LinQ 对自定义对象求和?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41865198/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com