2009-06-23 29 views
9

Tôi đang cố gắng để viết một phương pháp như thế này:Tôi biết typeof (T) nhưng trình biên dịch thì không. Làm thế nào để khắc phục?

public static T Test<T>() 
{ 
    if (typeof(T)==typeof(string)) 
    return "1241"; 

    // do something else 
} 

nhưng tôi dường như không thể tìm ra cách để kéo nó ra khỏi. Tôi muốn trả về các giá trị tùy thuộc vào loại T mà phương thức được gọi với. Tôi cần phải trả về chuỗi, int, các lớp tùy chỉnh, Danh sách, vv ..

Cách sử dụng thực tế là một số mã tuần tự tùy chỉnh, trong đó mã deserializing biết loại đối tượng cần tạo.

Làm rõ: ví dụ trên cho các lỗi sau: Không thể chuyển đổi chuỗi để gõ T

Các giải pháp lý tưởng sẽ làm việc trên các loại giá trị và các loại tài liệu tham khảo, và sẽ không bao gồm một tham số giả để giải quyết tình trạng quá tải.

Tôi bắt đầu nghi ngờ liệu giải pháp lý tưởng đó có tồn tại hay không.

Xin cảm ơn, Lucas

+0

typeof (T) nên để làm việc. Trình biên dịch phát hành thông báo lỗi nào? –

Trả lời

13

Dàn diễn viên trung gian để object không phải là lý tưởng, nhưng một cái gì đó như thế này nên làm như lừa:

public static T Test<T>() 
{ 
    if (typeof(T) == typeof(string)) 
     return (T)(object)"1241"; 

    // do something else 
} 
+0

Ah crap, tôi chỉ nói rằng quá! :) – leppie

6

Bạn phải truyền giá trị trả lại cho T, ví dụ: một cái gì đó như thế này cho các loại tài liệu tham khảo:

public static T Test<T>() where T : class 
{ 
    if (typeof(T)==typeof(string)) 
    return "1241" as T; 

    return default(T); 
} 
+0

Trình biên dịch nói: Không thể chuyển đổi loại 'chuỗi' thành T –

+0

Xin lỗi, tôi đã cập nhật mẫu. Lưu ý phần "nơi T: lớp". – M4N

+0

chỉ có vấn đề bây giờ là T phải là một lớp, do đó, sẽ không làm việc cho int, dài, vv –

5

Hãy coi chừng! Giải pháp bên dưới thực hiện không phải hoạt động (được xác minh bằng Trình biên dịch C# Mono gmcs C#).

Tuy nhiên, nó nên hoạt động bằng cách đọc tiêu chuẩn C#, vì độ phân giải quá tải nên ưu tiên phiên bản không chung của phương thức khi có thể. Phần liên quan trong ECMA-334 là 25.1.7: “Quá tải trong các lớp học chung”. Hơn nữa, Eric Lippert dường như cũng nói như vậy trong một số blog posting.

Phản hồi sẽ được đánh giá cao: tại sao điều này không hoạt động như mong đợi?


Bạn đã có loại không liên quan và không liên quan hành vi: mã này hét lên “! sử dụng quá tải

Generics sẽ là thích hợp với nhiều loại không liên quan, hành vi chưa giống hệt nhau (hoặc gần giống).

Làm điều này (chương trình thử nghiệm hoàn chỉnh để tái tạo hành vi):

using System; 

class TestClass { 
    public static T Test<T>() { 
     return TestWith(default(T)); 
     // do something else 
    } 

    public static string TestWith(string dummy) { 
     // Used only for `string`. 
     return "string"; 
    } 

    public static T TestWith<T>(T dummy) { 
     // Used for everything else. 
     return dummy; 
    } 

    static void Main() { 
     Console.WriteLine("Expected \"0\", got \"{0}\"", Test<int>()); 
     Console.WriteLine("Expected \"string\", got \"{0}\"", Test<string>()); 
    } 
} 

Biên soạn với gmcs, sản lượng này:

Expected "0", got "0" 
Expected "string", got "" 

Ở đây, tham số chỉ phục vụ cho định hướng của cuộc gọi quá tải. Không thể sử dụng các tham số chung rõ ràng ở đây vì một trong các hàm (chuyên môn string) không phải là chung.

+0

Kiểm tra vẫn gọi TestWith thay vì TestWith (chuỗi) –

+0

Patrick: damn. thật. Tôi chắc rằng tôi đã sử dụng cái này rồi. Trở lại với bản vẽ. –

+0

Xin lỗi, tôi không hiểu vấn đề là gì. Bạn có thể cung cấp một chương trình thực sự biên dịch và hiển thị đầu ra mà bạn không mong đợi? –

2

Hãy thử

public static T Test<T>() where T : class 
{ 
    if (typeof(T) == typeof(string)) return "asdf" as T; // do something else 
    // do something else   
} 
+1

Làm một cụm cứng "(T)" thay vì sử dụng "làm T". Sau đó, bạn có thể loại bỏ mệnh đề where. – Jehof

+0

@Jehof: nhưng mã sẽ không biên dịch nữa. Vì vậy không, đừng làm thế. –

+0

@Konrad. Tất nhiên bạn có quyền. Điều này không làm việc – Jehof

1

Bạn có thể sử dụng ChangeType?

public static T Test<T>() 
{ 
    if (typeof(T)==typeof(string)) 
     return (T)Convert.ChangeType("1234", typeof(T), CultureInfo.InvariantCulture); 
    return default(T); 
} 
0

Tôi tìm thấy giải pháp:

public static T Test<T>() 
{ 
    if (typeof(T) == typeof(string)) 
    return (T)(object)"1241"; // this works. 

    // do something else 
} 

Cảm ơn tất cả các câu trả lời .

+0

Hãy kiểm tra câu trả lời của Luke, anh ấy đã đưa ra giải pháp tương tự như bạn –

0
public static T Test<T>() 
{ 
    if (typeof(T)==typeof(string)) 
    return (T)Convert.ChangeType("1241", typeof(T)); 

    return default(T); 
} 

tôi đã không kiểm tra nó mặc dù :-)

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