2014-09-05 15 views
9

Tôi đang cố gắng tạo một phương thức chung trong C#, sẽ gọi các phương thức khác nhau dựa trên kiểu dữ liệu đối số trong phần thân của nó và xử lý kết quả của chúng sau đó. Tôi đang cố gắng để đạt được điều này bằng cách tạo ra một phương thức wrapper chung và sau đó cung cấp một số quá tải của phương thức xử lý - bao gồm cả một quá trình chung sẽ được sử dụng nếu không có quá tải cụ thể.C#: Phương pháp chung không gọi quá tải phương thức cụ thể

Khi tôi gọi phương thức xử lý trực tiếp, phiên bản thích hợp được chọn đúng. Tuy nhiên khi tôi gọi nó từ phương thức wrapper nó luôn luôn chọn một generic, ngay cả khi có một quá tải phù hợp với kiểu dữ liệu cụ thể mà tôi đã truyền cho nó.

Có cách nào để điều chỉnh mã để làm cho mã hoạt động theo cách tôi cần không? Hay tôi phải sử dụng một cách tiếp cận khác.

Tôi cần mã tương thích với Mono 2.6.

using System; 

class Program 
{ 
    static void Func<T>(T val) 
    { 
     Console.WriteLine("Generic Func"); 
    } 

    static void Func(int val) 
    { 
     Console.WriteLine("Int Func"); 
    } 

    static void Func(string val) 
    { 
     Console.WriteLine("String Func"); 
    } 

    static void FuncWrap<T>(T val) 
    { 
     Console.Write("Wrap: "); 
     Func(val); 
    } 

    static void Main(string[] args) 
    { 
     Func(2); 
     Func("Potato"); 
     Func(2.0); 

     FuncWrap(2); 
     FuncWrap("Potato"); 
     FuncWrap(2.0); 

     Console.Read(); 
    } 
} 
+0

bạn có thể có quá tải FuncWrap mất một int và chuỗi là tốt (hoặc chỉ sử dụng các phương thức Func trực tiếp mà không cần gói). –

Trả lời

13

Có cách nào khắc phục hành vi này không?

Đó là hành vi đúng theo đặc tả ngôn ngữ C#. Tình trạng quá tải của Func được gọi là trong số FuncWrap thường được xác định tại thời gian biên dịch, do đó, nó không thể chọn mức quá tải Func khác nhau dựa trên loại thời gian thực hiện.

Một cách để thay đổi hành vi, tuy nhiên, là sử dụng gõ động:

static void FuncWrap<T>(T val) 
{ 
    Console.Write("Wrap: "); 
    dynamic x = val; 
    Func(x); 
} 

Đó bây giờ sẽ thực hiện giải quyết tình trạng quá tải ở thời gian thực hiện dựa trên thực tế loại giá trị của x. Điều này phát sinh một chi phí hiệu suất, nhưng nên làm những gì bạn muốn nó.

Ngoài ra, bạn có thể mã hóa cứng kiến ​​thức về quá tải:

static void FuncWrap<T>(T val) 
{ 
    Console.Write("Wrap: "); 
    if (typeof(T) == typeof(string)) 
    { 
     Func((string)(object)val); 
    } 
    else if (typeof(T) == typeof(int)) 
    { 
     Func((int)(object)val); 
    } 
    else 
    { 
     Func(val); 
    } 
} 

Đó là rõ ràng khá khủng khiếp mặc dù.

+0

Xin lỗi, tôi đã không viết đúng. Tôi có nghĩa là "chính xác" như trong làm cho nó hoạt động theo cách tôi cần. Tính năng động dường như không hoạt động với Mono 2.6 (Tôi đang sử dụng mã trong công cụ Unity). Vâng, phương pháp thứ hai là không mong muốn, tôi đang tìm kiếm thứ gì đó sạch hơn (và lý tưởng là nhanh hơn). –

+0

@TomFrooxiusMariank: Nhìn vào các ghi chú phát hành cho Mono 2.6, nó * nên * được hỗ trợ - có thể là Unity thực sự giới hạn mọi thứ cho một cấu hình cũ hơn. (Nó sẽ cần cấu hình .NET 4.) Nếu không có 'dynamic', bạn có lẽ sẽ là tốt nhất với hack ở phần cuối của câu trả lời của tôi ... nó sẽ hoạt động khá tốt (tốt hơn năng động, cơ bản là sử dụng phản ánh). Bạn có thể sử dụng sự phản chiếu của mình tất nhiên, nhưng điều đó sẽ không nhanh. Nếu không ai trong số này là phù hợp, bạn có lẽ nên xem xét một thiết kế lại. –

+0

Tôi hiểu, có lẽ tôi không may mắn với phiên bản Unity Unity hiện tại, tôi sẽ kiểm tra xem liệu tôi có thể thay đổi hồ sơ bằng cách nào đó hay không, nhưng tôi không chắc liệu điều đó sẽ không có một số hậu quả không mong muốn. Nếu nó không hoạt động, tôi có thể sẽ làm lại mã để tránh tính năng này. Cảm ơn sự giúp đỡ của bạn. –

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