2017-01-26 7 views
1

まず、私は私のお金のオブジェクトを作成するには、このチュートリアルに従っ:https://www.codeproject.com/articles/837791/money-patternカスタムオブジェクトをLinQで合計するにはどうすればよいですか?

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

私はy.Amountにコンパイル例外が出ます:「?長い」

は、暗黙的にタイプ 「マネー」を変換できません。ブロック内 のいくつかの戻り値の型が デリゲートの戻り値の型私が間違っているのは何

に暗黙的に変換されないため、意図したデリゲート型にラムダ式を変換しませ することはできますか?ここで

は私のお金のクラスです:おそらく

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 
+1

y.Amount.Amountを試しますか? – shole

+0

@shole本当に?はい、もちろんですが、私はMoneyクラスのすべての利点を失っています。 –

+1

私はあなたの質問の全体的な点を逃しています、あなたは演算子をオーバーライドしようとしていて、LINQにMoneyの合計をさせようとしています(y.AmountはMoneyです...それは混乱しています!!)。お手伝いしますか? http://stackoverflow.com/questions/17717858/linq-sum-on-objects – shole

答えて

4

InvoiceDetailspublic 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を紹介したいかもしれません。またはMoneyためnull値を受け入れるために、静的な事業者を変更し、実行します。

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()はありません。そのようなシナリオでは、共通のインタフェースまたは型の推論が存在しません。 (Is there a constraint that restricts my generic method to numeric types?を参照してください。答えは"no"です)もちろん、独自の算術を提供するタイプをサポートする独自のバージョンのEnumerable.Sum()を追加することもできます。開始する場所はthis answerです。

0

オブジェクトを集計できる型に変換する暗黙の演算子を追加できます。

public static implicit operator decimal(Money money) { 
    return money != null ? money.Amount : 0; 
} 
1

@ dbcの回答に似ています。 Sumメソッドの独自の具体例を作成する必要があります。これは、operatorが静的​​であり、インターフェイス可能ではないためです。

Enumerable.First()の使用量がIEnumerable

  • Enumerable.First()の複数の反復は、要素がないと失敗しますが、貧弱な例外を与える原因となる

    1. ので、私は実際には、DBCからわずかに異なるルートを行くだろう。
    2. コードを再利用するとわかりやすくなります。

    代わりに私は好きです。

    namespace System.Linq //Using System.Linq namespace makes it easier to use 
    { 
        public static class MoneyEnumerable 
        { 
         public static Money Sum(this IEnumerable<Money> monies) 
         { 
          return monies.Aggregate((left, right) => left + right); 
         } 
        } 
    } 
    
  • 関連する問題