2016-12-16 7 views
5

संक्षिप्त:
मेरे पास एक विधि decimal GetAmount(IThing thing) है। things.Sum(GetAmount) का उपयोग CS0121 त्रुटि में परिणाम: कॉल Sum(Func<T, int>) और Sum(Func<T, int?>) के बीच संदिग्ध है। क्यूं कर?LINQ.Sum() int और int के बीच संदिग्ध decimals के साथ क्यों है?

अब:

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?>)'

मैं कुछ हद तक समझ में होगा अगर संकलक decimal और decimal? के बीच या यदि संकलक कई योग भार के के किसी भी लेने नहीं कर सकता है उलझन में था। लेकिन क्यों/कैसे यह अपने आप के लिए एक ही int और int?

Btw, वी.एस./आर # 'काम आते हुए' को सीमित था एक त्रुटि के रूप में .Sum() को GetAmount गुजर प्रकाश डाला गया और बजाय विधि लौटने एक पूर्णांक गुजर सुझाव देता है। संकलक इस भाग को दूसरी त्रुटि के रूप में ध्वजांकित नहीं करता है। बदलना 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

मुझे लगता है कि ऐसा इसलिए है क्योंकि संकलक केवल उनके रिटर्न-प्रकार के कारण विधियों को अलग नहीं कर सकता है। हालांकि मुझे आश्चर्य है कि कंपाइलर को * अंतर करने के लिए * जरूरत क्यों है, क्योंकि केवल एक ही विधि है। हालांकि अच्छा सवाल है। – HimBromBeere

+0

मुझे नहीं पता कि int कहाँ से आया था, लेकिन मैं [decimals के साथ त्रुटि प्राप्त कर रहा हूं] (https://dotnetfiddle.net/ZoCY2G) – Reniuz

+1

@mybirthname यह तब तक काम करता है जब यह अनुमान लगाने के लिए एक अनौपचारिक विधि है * ओपीएस मामले में * है। – HimBromBeere

उत्तर

4

आपके पास .Sum() का अधिभार नहीं है जहां आप अपनी विधि पारित कर सकते हैं।

आप सही आप इसे इस तरह से कर सकते हैं:

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

thing => GetAmount(thing) - इस भाग मूल रूप से anonymouse समारोह पैदा करेगा और .Sum() इसके लिए अधिभार मिला है। (मैं वी.एस. 2015 उपयोग

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

असल में मैं अपने कोड के साथ एक और संकलक त्रुटि मिलती है:

इसे लागू करने के अन्य तरीकों में से एक (अधिक obviouse रास्ता तो तुम क्या वास्तव में happends समझ सकते हैं) अपने आप को समारोह बनाने है)।

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

तो मुझे लगता है कि आपको केवल वायर्ड त्रुटि मिलती है क्योंकि प्रीकंपलर एनालिज़र सही नहीं है।

मैं थोड़ा और अधिक शोध किया और इस तरह कमांड प्रॉम्प्ट से precompiler के बिना अपने कोड को संकलित करने का प्रयास करें: सही त्रुटि वापस

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 प्रकार के साथ सही त्रुटि मिली। तो wierd संकलक त्रुटि है कि हम precompiler स्रोतों में कहीं कहीं स्थित हो।

+1

हम्म, जब मैं 'वापसी चीजें' का उपयोग करता हूं। (नया Func (GetAmount)); 'मुझे कोई कंपाइलर त्रुटि नहीं मिलती है। यहाँ क्या चल रहा है? मैं वीएस2015 का उपयोग कर रहा हूँ। –

+0

@IvanStoev मुझे ओपी कोड के साथ इस कंपाइलर त्रुटि मिलती है - 'सार्वजनिक दशमलव कुल (आईटिंग [] चीजें) {वापसी चीजें। Sum (GetAmount); } ' –

+0

मैं देखता हूं। अभी भी अजीब है क्योंकि मुझे ओपी के समान त्रुटि मिलती है :) –

1

CS0121 से जुड़े त्रुटि संदेश केवल पहले दो संदिग्ध मैचों को प्रदर्शित करता है। त्रुटि 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>)' 

एक विधि की वापसी प्रकार यह के हस्ताक्षर का हिस्सा बनने का विचार नहीं किया है। फिर आप ही नाम के दो तरीकों कि केवल वापसी प्रकार में अलग लिख कर यह साबित कर सकते हैं: जब Sum की एक अधिभार कि सही हस्ताक्षर के साथ एक Func स्वीकार करता है की तलाश में

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 

तो, केवल मापदंडों माना जाता है, नहीं रिटर्न प्रकार, इस मामले में IThing, जो इसे Sum के सभी ओवरलोड से मेल खाता है और इसलिए संदिग्ध हो जाता है।

संबंधित मुद्दे