首先,我按照本教程创建了我的Money对象:https : //www.codeproject.com/articles/837791/money-pattern
Money totalItems = _invoice.InvoiceDetails .Sum(y => y.Amount); // Amount is of type Money
我在上收到编译异常y.Amount
:
无法将类型'Money'隐式转换为'long?' 无法将lambda表达式转换为预期的委托类型,因为该块中的某些返回类型不能隐式转换为委托返回类型
我究竟做错了什么?
这是我的Money课程:
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
dbc.. 5
大概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
不包含任何货币并且可以添加到任何类型的货币的特殊单例。或修改静态运算符以接受的null
值Money
并执行以下操作:
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()
引入了算术运算符重载的任意类型,因为在这种情况下没有通用的接口或类型推断。(请参见是否存在将我的泛型方法限制为数值类型的约束?答案为“否”。)当然,您可以添加自己的版本,Enumerable.Sum()
以支持提供自己的算术类型,请参见此答案为一个开始的地方。
大概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
不包含任何货币并且可以添加到任何类型的货币的特殊单例。或修改静态运算符以接受的null
值Money
并执行以下操作:
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()
引入了算术运算符重载的任意类型,因为在这种情况下没有通用的接口或类型推断。(请参见是否存在将我的泛型方法限制为数值类型的约束?答案为“否”。)当然,您可以添加自己的版本,Enumerable.Sum()
以支持提供自己的算术类型,请参见此答案为一个开始的地方。