2016-12-16 18 views
5

ngắn:
Tôi có phương thức decimal GetAmount(IThing thing). Sử dụng things.Sum(GetAmount) kết quả trong lỗi CS0121: cuộc gọi không rõ ràng giữa Sum(Func<T, int>)Sum(Func<T, int?>). Tại sao?Tại sao Linq.Sum() với số thập phân không rõ ràng giữa int và int?

còn:

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

Tôi hơi sẽ hiểu nếu trình biên dịch đã nhầm lẫn giữa decimaldecimal? hoặc nếu trình biên dịch không thể chọn bất kỳ của nhiều quá tải Sum. Nhưng tại sao/làm thế nào nó tự giới hạn để chỉ intint?

Btw, VS/R # 'helpfully' làm nổi bật qua GetAmount-.Sum() như một lỗi và đề nghị thông qua một phương pháp int trở về để thay thế. Trình biên dịch không gắn cờ phần này là lỗi thứ hai. Thay đổi GetAmount thành int GetAmount(IThing thing) thực sự làm 'giải quyết' lỗi trình biên dịch.

ps. Tôi không tìm kiếm một giải pháp cho lỗi trình biên dịch. Tôi biết tôi có thể biến GetAmount thành Func<IThing, decimal> GetAmount { get; } hoặc triển khai Tổng số như things.Sum(thing => GetAmount(thing)). Và theo đề xuất của @IvanStoev, things.Sum(new Func<IThing, decimal>(GetAmount)) cũng hoạt động (đối với tôi).

+1

Tôi cho rằng đó là do trình biên dịch không thể thực hiện các phương thức ditinguish chỉ vì kiểu trả về của chúng. Tuy nhiên tôi tự hỏi tại sao trình biên dịch thậm chí * cần * để phân biệt, vì chỉ có một phương pháp. Câu hỏi hay. – HimBromBeere

+0

Tôi không biết int đến từ đâu, nhưng tôi [nhận lỗi với số thập phân] (https://dotnetfiddle.net/ZoCY2G) – Reniuz

+1

@mybirthname Tác phẩm này miễn là có một phương pháp rõ ràng để suy ra nó * là * trong trường hợp OP. – HimBromBeere

Trả lời

4

Bạn chỉ không bị quá tải .Sum() nơi bạn có thể chuyển phương thức của mình.

Bạn phải bạn có thể làm điều đó theo cách đó:

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

thing => GetAmount(thing) - phần này về cơ bản sẽ tạo ra chức năng anonymouse và .Sum() có tình trạng quá tải cho nó.

Một trong những cách khác để thực hiện nó (hơn obviouse cách để bạn có thể hiểu những gì thực sự happends) là tạo func mình:

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

Trên thực tế tôi nhận được một lỗi biên dịch với mã của bạn (tôi sử dụng VS 2015).

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

Vì vậy, tôi nghĩ rằng bạn gặp phải lỗi có dây đó chỉ vì trình biên dịch tiền biên dịch không hoàn hảo.

tôi đã nghiên cứu nhiều hơn một chút và cố gắng để biên dịch mã của bạn mà không cần tiền biên dịch từ dấu nhắc lệnh như thế này:

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

Và bây giờ biên dịch lỗi ngay trở lại:

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

Như bạn thấy bây giờ chúng tôi đã nhận được lỗi đúng với loại decimal. Vì vậy, lỗi trình biên dịch tồi tệ hơn mà chúng tôi nhận được nằm ở đâu đó trong các nguồn trình biên dịch trước.

+1

Hmm, khi tôi sử dụng 'return things.Sum (new Func (GetAmount));' Tôi không nhận được bất kỳ lỗi trình biên dịch nào. Những gì đang xảy ra ở đây? Tôi đang sử dụng VS2015. –

+0

@IvanStoev tôi nhận được lỗi trình biên dịch này với mã OP - 'công thập phân Tổng số (IThing [] điều) {return things.Sum (GetAmount); } ' –

+0

Tôi hiểu. Vẫn còn lạ vì tôi gặp lỗi giống như OP :) –

1

Thông báo lỗi liên kết với CS0121 chỉ hiển thị hai kết quả không rõ ràng đầu tiên. Lỗi áp dụng cho tất cả chữ ký của Sum.Bạn có thể chứng minh điều này bản thân bằng cách viết một lớp mở rộng phù hợp với chữ ký Sum và chuyển đổi thứ tự của các phương pháp trong lớp:

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

Kiểu trả về của một phương pháp không được coi là một phần của chữ ký của nó. Một lần nữa, bạn có thể chứng minh điều này bằng cách viết hai phương pháp có cùng tên chỉ khác nhau về kiểu trả về:

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 

Vì vậy, khi tìm kiếm một tình trạng quá tải của Sum chấp nhận một Func với chữ ký đúng, chỉ có các thông số được coi là, không các kiểu trả về, trong trường hợp này là IThing, làm cho nó khớp với tất cả các tình trạng quá tải của Sum và do đó không rõ ràng.

Các vấn đề liên quan