2008-11-19 16 views
418

Mam metoda rodzajowa z tym (obojętne) kodu (tak jestem świadomy IList ma predykaty, ale mój kod nie używa IList, ale jakiś inny zbiór, w każdym razie to nie ma znaczenia dla kwestii ...)Jak mogę zwrócić NULL z ogólnej metody w C#?

static T FindThing<T>(IList collection, int id) where T : IThing, new() 
{ 
    foreach T thing in collecion 
    { 
     if (thing.Id == id) 
      return thing; 
    } 
    return null; // ERROR: Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead. 
} 

to daje mi błąd kompilacji

„nie można przekonwertować wartość null, aby wpisać parametr «T», ponieważ może to być typ wartości. Rozważ użycie«default (T)»zamiast”.

Czy mogę uniknąć tego błędu?

+1

dlaczego to jest wiki tej społeczności? – vitule

+2

Przyczyna Myślałem, że to sprawia, że ​​społeczność tych pytań jest edytowalna? – edosoft

Odpowiedz

741

dwie opcje:

  • powrotu default(T) co oznacza wrócisz null jeśli T jest typem odniesienia (lub typ wartości pustych), 0 dla int, '\ 0' dla char itp
  • ograniczyć T, aby być typem odniesienia z where T : class przymusu, a następnie powrót null jako normalny
+3

Co się stanie, jeśli mój typ zwrotu to wyliczenie, a nie klasa? Nie mogę określić T: enum :( – Justin

+1

W .NET enum jest bardzo cienkim (i raczej nieszczelnym) otokiem wokół typu integer. Konwencja ma używać zero dla "domyślnej" wartości wyliczeniowej. –

+18

Myślę, że problem oznacza to, że jeśli używasz tej ogólnej metody do powiedzenia, przekonwertuj obiekt bazy danych z DbNull na Int i zwróci wartość domyślną (T), gdzie T jest int, zwróci 0. Jeśli ta liczba jest rzeczywiście znacząca, to przekazywałbyś złe dane w przypadkach, w których pole było zerowe, lub lepszym przykładem byłby DateTime. Jeśli pole było podobne do "DateClosed" i zostało zwrócone jako null, ponieważ konto i konto są nadal otwarte, to faktycznie domyślnie (DateTime) do 1/1/0000, co oznacza, że ​​konto zostało zamknięte przed wynalezieniem komputerów. – Sinaesthetic

61
return default(T); 
+0

Ten link: http://msdn.microsoft.com/en-us/library/xwth0h0d(VS.80).aspx powinien wyjaśnić, dlaczego. –

+0

Cholera, zaoszczędziłbym wiele czasu, gdybym wiedział o tym słowie kluczowym - dziękuje Ricardo! –

+0

Jestem zaskoczony, że to nie zdobyło więcej głosów, ponieważ "domyślne" słowo kluczowe jest bardziej wszechstronnym rozwiązaniem, pozwalającym na użycie typów niezwiązanych z referencjami w połączeniu z typami liczbowymi i strukturami. Chociaż zaakceptowana odpowiedź rozwiązuje problem (i rzeczywiście jest pomocna), lepiej odpowiada, jak ograniczyć typ zwracania do typów zerowujących/referencyjnych. –

1

Weź rekomendację błędu ... i albo użytkownik default(T) lub new T.

Będziesz musiał dodać w swoim kodzie porównanie, aby upewnić się, że jest to poprawne dopasowanie, jeśli jedziesz tą trasą.

W przeciwnym razie potencjalnie można rozważyć parametr wyjściowy dla "znalezionego dopasowania".

5

Twój innych opcji byłoby dodać to do końca swojej deklaracji:

where T : class 
    where T: IList 

W ten sposób pozwoli ci zwrócić wartość null.

22

Można tylko dostosować swoje ograniczenia:

where T : class, IDisposable 

Następnie powrocie zerowy jest dozwolone.

+0

Dzięki. Nie mogę wybrać 2 odpowiedzi jako przyjętego rozwiązania, więc wybieram sprawę Johna Skeeta, ponieważ jego odpowiedź ma dwa rozwiązania. – edosoft

+5

Nieco źle, to nie musi być IDisposable ... – Migol

10

Dodaj wiązanie klasy jako pierwsze ograniczenie do typu ogólnego.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new() 
+0

Dzięki. Nie mogę wybrać 2 odpowiedzi jako przyjętego rozwiązania, więc wybieram sprawę Johna Skeeta, ponieważ jego odpowiedź ma dwa rozwiązania. – edosoft

1

rozwiązanie TheSoftwareJedi działa

również można zarchiwizować je za pomocą kilku typów wartości i pustych:

static T? FindThing<T>(IList collection, int id) where T : struct, IThing 
{ 
    foreach T thing in collecion 
    { 
     if (thing.Id == id) 
      return thing; 
    } 
    return null; 
} 
5
  1. Jeśli masz obiekt następnie trzeba typecast

    return (T)(object)(employee); 
    
  2. , jeśli chcesz zwrócić wartość null.

    return default(T); 
    
+0

Witaj user725388, zweryfikuj pierwszą opcję –

1

Oto przykład pracując dla wartości zwracanych Nullable ENUM:

public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct 
{ 
    return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value); 
} 
1

Poniżej opcja dwa można użyć

return default(T); 

lub

where T : class, IDisposable 
return null; 
Powiązane problemy