2010-01-22 10 views
5

Czy mam coś takiego:Korzystanie z metod ogólnych, czy możliwe jest odzyskanie różnych typów z tej samej metody?

int x = MyMethod<int>(); 
string y = MyMethod<string>(); 

więc jedna metoda powrocie różnych typów w oparciu o T. Oczywiście, nie byłoby logiki wewnątrz metody, aby zapewnić, że wracał poprawną rzeczą.

Nigdy nie uda mi się uruchomić czegoś takiego. twierdzi on, że nie może rzutować wartości zwracanej do T:

public static T MyMethod<T>() 
{ 
    if(typeof(T) == typeof(Int32)) 
    { 
    return 0; 
    } 
    else 
    { 
    return "nothing"; 
    } 
} 
+4

F irst ze wszystkich, ten kod nie będzie się kompilował, ponieważ nie ma określonego typu zwracanego. Zakładam, że chcesz, aby przeczytał 'public static T MyMethod ()' – Nick

+0

Dodaj to jako odpowiedź, Nick. Myślę, że to rozwiązanie, którego potrzebuje. – JMD

+0

... chociaż ten kod, jak napisano powyżej, nadal nie będzie się kompilował, ponieważ "nic" nie jest T, chyba że T jest łańcuchem, a 0 nie jest T, chyba że T jest typem liczbowym. – JMD

Odpowiedz

10

Wypróbuj następujące

public static T MyMethod<T>() { 
    if (typeof(T) == typeof(Int32)) { 
    return (T)(object)0; 
    } else { 
    return (T)(object)"nothing"; 
    } 
} 

Sztuką jest tu odlewania do object. To, co próbujesz zrobić, jest z natury niebezpieczne, ponieważ kompilator nie może wywnioskować, że 0 lub "nic" jest zamienne na dowolne dane T. W końcu jest nieograniczona. Więc po prostu powiedz kompilatorowi, że nie jest to bezpieczne z rzutowaniem na object.

+0

To działa. A więc, jedyne, co robisz inaczej, rzucasz najpierw na obiekt, a potem na T? – Deane

+1

Podczas gdy rozwiązuje to błąd czasu kompilacji, ale nadal nie ma sensu. Jeśli T jest, powiedzmy, typem strony, to nie ma sensu zwracać ciągów do T za pomocą tego (obiektu) hackowania. Kompiluje się tylko dlatego, że zarówno łańcuchy, jak i liczby całkowite mogą być rzutowane na obiekt, a obiekty mogą być przypadkami dla ich typów potomnych (tj. Wszystkiego). –

0

Możesz zrobić, jeśli chcesz zwrócić wartość typu "null", jeśli nie jest to int. Ale jeśli chcesz mieć ciąg we wszystkich innych przypadkach, sprawdź inne odpowiedzi.

public static T MyMethod<T>() 
{ 
    if(typeof(T) == typeof(Int32)) 
    { 
    return (T)(object)0; 
    } 
    else 
    { 
    return default(T); // or null 
    } 
} 
+0

Dla próbki łańcuchowej OP chce, aby zwrócił określoną wartość ciągu, a nie wartość domyślną (T). Brakuje również typu zwrotu. – JaredPar

+0

Prawda .. i brakuje mi tego, ponieważ skopiowałem kod i opuściłem tę część przed edycją. –

+0

To nie zadziała - nie ma konwersji między int i T – Lee

0

@Nick jest poprawny w swoim komentarzu, że twój kod się nie skompiluje. Ale zakładając, że masz na myśli:

public static T MyMethod<T>() 
{ 
    if(typeof(T) == typeof(Int32)) 
    { 
    return 0; 
    } 
    else 
    { 
    return "nothing"; 
    } 
} 

Jest to może być trudne, aby generyczne non generic jak próbujesz (i rzeczywiście narusza cały punkt), ale to powinno działać:

public static T MyMethod<T>() 
{ 
    if(typeof(T) == typeof(Int32)) 
    { 
    return (T)(object)0; 
    } 
    else if(typeof(T) == typeof(string)) 
    { 
    return (T)(object)"nothing"; 
    } 

    return default(T); 
} 
+0

Tak, to było to samo rozwiązanie, co powyżej. Zakładam, że najpierw musiałem rzucić obiekt, ponieważ nie ma bezpośredniego rzutu od int do T. Ale istnieje odlew od int do obiektu i obiekt do T. Czy to prawda? – Deane

+0

Bo sprawdzasz typeof (T) tak. Naprawdę, klauzula else powinna sprawdzić typeof (string) w przeciwnym razie coś takiego jak MyMethod zawiedzie. Będę edytować przykład. – dkackman

0

Ten ISN” t ważne, ponieważ nie ma gwarancji, że T można rzutować/konwertować na ciąg lub int.

Generics NIE są wariantami - tzn. Typami, które mogą pomieścić cokolwiek - są kompilowane w czasie rzeczywistym. Twój kod nie kompiluje się, ponieważ nie powinien. Możesz obejść problemy z kompilacją za pomocą niektórych hacków zamieszczonych tutaj, ale jest to naprawdę problem logiczny. Odsuń się i przemyśleć, co chcesz zrobić, zamiast próbować ominąć kompilator.

+0

Czy mogę w jakiś sposób ograniczyć T do stringów lub int? – Deane

+0

@Deane - nie możesz – dkackman

+0

@Deane - W VB lub w podobnych językach skryptowych możesz zwrócić cokolwiek chcesz z funkcji - int, string, float, page, webservice reference, co ty. W mocno napisanych językach, tak nie jest - ponieważ kompilator oczekuje, że przejmiesz kontrolę nad panowaniem i nie pozwolisz mu wykonywać swojej pracy za ciebie. Jak wygląda CALLING CODE, że potrzebujesz tego rodzaju rezultatów ?! –

1

Lekko off topic, ale jeśli starasz się zrobić to wtedy może się okazać, że projekt jest zły ...

Dlaczego nie przeciążać metody i ustawić wynik jako out paramter:

void MyMethod(out int result) 
{ 
    result=0; 
} 

void MyMethod(out string result) 
{ 
    result="my value"; 
} 

Wtedy można powiedzieć:

int value; 
MyMethod(out value); 

i kompilator wybierze właściwą wersję

+0

Czy to nie jest właściwe użycie generyków, aby móc używać tej samej logiki dla różnych typów? Po prostu mam metodę, która ma sporo logiki, ale w różnych sytuacjach potrzebuję od niej różnych typów. Czy nie jest to właściwy sposób na użycie leków generycznych? – Deane

+0

Ale włączasz typ, co może spowodować problem ... Dodam alternatywę – Sean

+0

Tak, to by działało. Wydaje się, że jest mniej wdzięczna, ponieważ mam teraz trzy metody - jedną dla każdego typu i jedną dla głównej logiki. Dlaczego włączasz problem? – Deane

Powiązane problemy