2012-12-09 38 views
6

Tôi muốn sử dụng các phương thức quá tải để nhận kết quả khác nhau theo các loại chung khác nhau. Nó không hoạt động. Mã của tôi cho thấy rõ ràng.lỗi quá tải C# cho loại chung

static class Helper 
{ 

    public static bool Can(int i) 
    { 
     return true; 
    } 

    public static bool Can(Object o) 
    { 
     return false; 
    } 
} 

class My<T> 
{ 
    public static bool can = Helper.Can(default(T)); 
} 

Console.WriteLine(Helper.Can(default(int)));//True,it is OK 

Console.WriteLine(My<int>.can);//false?? why the overload doesn't work 
Console.WriteLine(My<Object>.can);//false 

Tại sao My<int> gọi Helper.Can (Object o) thay vì Helper.Can (int i)?

Trả lời

4

Nó không hoạt động theo cách đó.

Quá tải được giải quyết hoàn toàn tại thời gian biên dịch; các tham số kiểu generic được giải quyết khi chạy.
Vì trình biên dịch không biết rằng Tint, mã của bạn sẽ luôn gọi Can(Object).

+0

Tuyệt vời.Cảm ơn bạn – zilong

+0

Tôi hoàn toàn không đồng ý với tuyên bố rằng "thông số loại chung được giải quyết khi chạy". Nếu đó là trường hợp, trình biên dịch không thể nói tại thời gian biên dịch mà bạn không thể có được một mục int từ một 'Danh sách '. * Những gì * được xem là chưa được giải quyết tại thời gian biên dịch là các lần xuất hiện của tham số kiểu generic trong lớp chung. –

+0

@ O.R.Mapper: Tôi có nghĩa là trong lớp học chung chung. – SLaks

1

nó là một chút dài dòng, nhưng bạn có thể đạt được những gì bạn muốn bằng cách sử dụng Reflection:

class My<T> 
{ 
    static bool doStuff() 
    { 
     var rightMehod = typeof(Helper).GetMethods().Where(p => 
      { 
       if (!p.Name.Equals("Can")) 
        return false; 

       if (!p.ReturnType.Equals(typeof(bool))) 
        return false; 

       if (p.GetParameters().Length != 1) 
        return false; 

       var par = p.GetParameters().First(); 
       return par.ParameterType.Equals(typeof(T)); 
      }).FirstOrDefault(); 

     if (rightMehod == null) 
     { 
      return Helper.Can(default(T)); 
     } 
     else 
     { 
      return (bool)rightMehod.Invoke(null, new object[] { default(T) }); 
     } 
    } 

    public static bool can = doStuff(); 
} 

Bằng cách này,

My<string>.can == false 
My<int>.can == true 
My<object>.can == false 

Tất nhiên, với một chút nghề bổ sung (và sử dụng các loại chung), bạn sẽ có thể sử dụng lại đoạn mã đó một cách rộng rãi cho nhiều tình huống khác nhau.

Một nhận xét bổ sung: trong ví dụ này, tôi đã sử dụng so sánh loại trực tiếp cho ví dụ cụ thể của bạn. Lưu ý rằng điều này sẽ không hoạt động đúng khi xử lý các kiểu thừa kế (và dĩ nhiên, cũng có một số sự mơ hồ bổ sung :).

3

Nói chung, nó sẽ giải quyết cho đối tượng tại thời gian biên dịch, nhưng bạn có thể nói với nó đợi cho đến khi thời gian chạy bằng cách sử dụng các từ khóa động:

class My<T> 
{ 
    public static bool can = CanWithDynamic(); 

    private static bool CanWithDynamic() { 
     dynamic runtimeT = default(T); 
     return Helper.Can(runtimeT); 
} 

Vì vậy, điều này sẽ làm việc cho những gì bạn đang cố gắng để làm và quá tải phải sẽ được gọi. Tuy nhiên, như với bất cứ điều gì được giải quyết trong thời gian chạy có một chi phí hiệu suất liên kết với nó. Có lẽ không nhiều, nhưng nếu bạn gọi phương pháp này thường xuyên nó có thể có tác động.

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