2016-12-16 9 views
5

短い:
私は方法がdecimal GetAmount(IThing thing)です。 things.Sum(GetAmount)を使用すると、CS0121エラーが発生します。Sum(Func<T, int>)Sum(Func<T, int?>)の間のコールはあいまいです。どうして?Linq.Sum()がintとintの間に曖昧な理由は何ですか?

長い:

public interface IThing { } 
public class Sample { 
    public decimal GetAmount(IThing thing) { return 0; } 
    public decimal Total(IThing[] things) { return things.Sum(GetAmount); } 
} 

Error CS0121 The call is ambiguous between the following methods or properties: 'Enumerable.Sum<TSource>(IEnumerable<TSource>, Func<TSource, int>)' and 'Enumerable.Sum<TSource>(IEnumerable<TSource>, Func<TSource, int?>)'

コンパイラはdecimaldecimal?間またはコンパイラは、多くの合計のオーバーロードのいずれかを選ぶことができなかった場合は混乱していた場合、私は多少理解するであろう。しかし、なぜ/どのようにそれはところでのみintint?

に自分自身を制限しなかった、VS/R#が「親切」エラーとして.Sum()GetAmountを渡す浮き彫りにし、代わりに方法を返すint型を渡すことを示唆しています。コンパイラは、この部分を2番目のエラーとしてフラグを立てません。 GetAmountからint GetAmount(IThing thing)に変更すると、実際にはコンパイラのエラーが解決されます。

ps。私はコンパイラエラーの解決策を探していません。 GetAmountをFunc<IThing, decimal> GetAmount { get; }にするか、things.Sum(thing => GetAmount(thing))のように合計を実装することができます。 @IvanStoevの提案によれば、things.Sum(new Func<IThing, decimal>(GetAmount))も(私にとっては)うまく動作します。

+1

私は、コンパイラが戻り値の型のためにメソッドをditinguishできないためだと思います。しかし、私はコンパイラが*なぜ*区別する必要があるのだろうと思っています。良い質問。 – HimBromBeere

+0

intがどこから来たのか分かりませんが、私は[小数点以下でエラーが出ます] – Reniuz

+1

@mybirthnameこれは、どのようなものかを推測する明確な方法がある限り、機能します* OPの場合*です。 – HimBromBeere

答えて

4

あなたのメソッドを渡すことができる.Sum()の過負荷はありません。

あなたは右のあなたがそのように行うことができます。

things.Sum(thing => GetAmount(thing)) 

thing => GetAmount(thing)

- この部分は基本的にanonymouse関数を作成し、 .Sum()はそれのために過負荷を得ました。

(あなたが実際にhappendsかを理解することができますので、より多くのobviouse方法は)それを実装する他の方法の一つを自分funcを作成されています

public decimal Total(IThing[] things) 
{ 
    return things.Sum(new Func<IThing, decimal>(GetAmount)); 
} 

実際に私は(私はVS 2015を使用してコードを持つ別のコンパイラエラーを取得するには)。

Severity Code Description Project File Line Suppression State Error CS0407 'decimal Sample.GetAmount(IThing)' has the wrong return type

したがって、私は、プリコンパイラ・アナライザが完璧でないために、ワイヤード・エラーが発生すると思います。

私はもう少し研究を行なったし、このようなコマンドプロンプトからプリコンパイラせずにあなたのコードをコンパイルしよう:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /t:exe /out:Program.exe Program.cs

そして今、右のエラーを返すコンパイラ:

Program.cs(13,56): error CS0121: The call is ambiguous between the following methods or properties: 'System.Linq.Enumerable.Sum<Lambda.IThing>(System.Collections.Generic.IEnumerable<Lambda.IThing>, System.Func<Lambda.IThing,decimal>)' and 'System.Linq.Enumerable.Sum<Lambda.IThing>(System.Collections.Generic.IEnumerable<Lambda.IThing>, System.Func<Lambda.IThing,decimal?>)'

あなたが今、私たちを見るようにdecimalタイプで正しくエラーが発生しました。私たちがプリコンパイラのソースのどこかに置かれてしまうような、コンパイラのエラーです。

+1

ええと、 'return things.Sum(new Func (GetAmount));'私はコンパイルエラーを受け取っていません。何が起きてる?私はVS2015を使用しています。 –

+0

@IvanStoev私はOPコードでこのコンパイラエラーを受け取ります - 'public decimal Total(IThing [] things){return things.Sum(GetAmount); } ' –

+0

私は参照してください。私はOPと同じエラーが発生するので、まだ変です:) –

1

CS0121に関連するエラーメッセージは、最初の2つの曖昧な一致のみを表示します。このエラーは、Sumのすべての署名に適用されます。あなたはSum署名と一致する拡張クラスを書いて、クラス内のメソッドの順序を切り替えることで、この自分自身を証明することができます。

public static class Extensions 
{ 
    public static decimal TestSum<T>(this IEnumerable<T> source, Func<T, decimal> selector) 
    { 
     return 0; 
    } 

    public static int TestSum<T>(this IEnumerable<T> source, Func<T, int> selector) 
    { 
     return 0; 
    } 

    public static int? TestSum<T>(this IEnumerable<T> source, Func<T, int?> selector) 
    { 
     return 0; 
    } 
} 

CS0121 The call is ambiguous between the following methods or properties: 
'Extensions.TestSum<T>(IEnumerable<T>, Func<T, decimal>)' and 
'Extensions.TestSum<T>(IEnumerable<T>, Func<T, int>)' 

メソッドの戻り値の型は、それの署名の一部とは見なされません。ない、正しいシグネチャを持つFuncを受け入れSumの過負荷を探しているときに、パラメータのみが考慮されている

public class TestClass 
{ 
    public decimal TestReturn(int value) { return 0m; } 
    public int TestReturn(int value) { return 0; } 
} 

CS0111 Type 'TestClass' already defines a member called 'TestReturn' with the same parameter types 

:ここでもあなただけの戻り値の型が異なる同じ名前の2つのメソッドを書くことによってこれを証明することができます戻り値の型はIThingで、Sumのすべてのオーバーロードに一致するため、あいまいです。

関連する問題