Chcę zrobić coś takiego:
myYear = record.GetValueOrNull<int?>("myYear"),
Zwróć uwagę na typ zerowalny jako parametr ogólny.
Ponieważ GetValueOrNull
funkcja może zwrócić null, moja pierwsza próba była następująca:
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : class
{
object columnValue = reader[columnName];
if (!(columnValue is DBNull))
{
return (T)columnValue;
}
return null;
}
Ale błąd, który teraz otrzymuję, to:
Wpisz „int?” musi być typem odniesienia, aby można go było używać jako parametru „T” w typie lub metodzie ogólnej
Dobrze! Nullable<int>
jest struct
! Próbowałem więc zmienić ograniczenie klasy na struct
ograniczenie (i jako efekt uboczny nie mogę już null
więcej powrócić ):
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : struct
Teraz zadanie:
myYear = record.GetValueOrNull<int?>("myYear");
Daje następujący błąd:
Wpisz „int?” musi być niedopuszczalnym typem wartości, aby użyć go jako parametru „T” w typie lub metodzie ogólnej
Czy w ogóle możliwe jest podanie typu zerowalnego jako parametru ogólnego?
IDataRecord
odDbDataRecord
...Odpowiedzi:
Zmień typ zwracany na Nullable i wywołaj metodę z parametrem innym niż nullable
źródło
Po prostu użyj tego w ten sposób:
źródło
GetValueOrDefault
wyjaśnić, że zwracadefault(T)
zamiastnull
. Alternatywnie możesz zgłosić wyjątek, jeśliT
nie ma wartości zerowej.Po prostu zrób dwie rzeczy z oryginalnym kodem - usuń
where
ograniczenie i zmień ostatniąreturn
zreturn null
nareturn default(T)
. W ten sposób możesz zwrócić dowolny typ.Nawiasem mówiąc, możesz uniknąć używania
is
, zmieniając swojeif
oświadczenie naif (columnValue != DBNull.Value)
.źródło
return default
wystarczający (nie potrzebujesz(T)
, kompilator wywnioskuje to na podstawie typu zwrotu podpisu).Oświadczenie: Ta odpowiedź działa, ale jest przeznaczona wyłącznie do celów edukacyjnych. :) Rozwiązanie Jamesa Jonesa jest prawdopodobnie najlepsze tutaj i na pewno takie, z którym bym poszedł.
Słowo
dynamic
kluczowe w C # 4.0 czyni to jeszcze łatwiejszym, jeśli mniej bezpiecznym:Teraz nie potrzebujesz wyraźnego podpowiedzi typu na RHS:
W rzeczywistości nawet go nie potrzebujesz!
value
będzie teraz liczbą całkowitą, ciągiem znaków lub dowolnym typem zwróconym z bazy danych.Jedynym problemem jest to, że nie przeszkadza to w używaniu typów nie dopuszczających wartości zerowej w LHS, w którym to przypadku otrzymasz dość nieprzyjemny wyjątek czasu wykonywania, taki jak:
Podobnie jak w przypadku wszystkich kodów, które używają
dynamic
: kodera zastrzeżeń.źródło
Musiałem zrobić coś niesamowitego do tego. Mój kod:
źródło
Myślę, że chcesz obsługiwać typy referencyjne i typy struktur. Używam go do konwersji ciągów elementów XML na bardziej typowe typy. Możesz usunąć nullAlternative z odbiciem. Dostawca formatu ma obsługiwać zależne od kultury „.” lub separator „,” np. ułamki dziesiętne lub liczby całkowite i podwójne. Może to działać:
Możesz użyć tego w następujący sposób:
źródło
To może być martwy wątek, ale zwykle używam następujących elementów:
źródło
Właśnie sam spotkałem ten sam problem.
... = reader["myYear"] as int?;
działa i jest czysty.Działa z każdym rodzajem bez problemu. Jeśli wynikiem jest DBNull, zwraca wartość null, ponieważ konwersja nie powiodła się.
źródło
int v=reader["myYear"]??-1;
lub użyć innej domyślnej opcji-1
. Może to jednak powodować problemy, jeśli wartość wynosiDBNull
...Wiem, że to stare, ale oto inne rozwiązanie:
Teraz nie obchodzi cię, czy
T
był to typ wartości czy referencyjny. Tylko jeśli funkcja zwróci true, masz rozsądną wartość z bazy danych. Stosowanie:To podejście jest bardzo podobne do
int.TryParse("123", out MyInt);
źródło
Wiele ogólnych ograniczeń nie może być łączonych w sposób OR (mniej restrykcyjny), tylko w sposób AND (bardziej restrykcyjny). Oznacza to, że jedna metoda nie obsługuje obu scenariuszy. Ograniczeń ogólnych nie można również użyć do utworzenia unikalnego podpisu dla metody, dlatego trzeba będzie użyć 2 oddzielnych nazw metod.
Można jednak użyć ogólnych ograniczeń, aby upewnić się, że metody są używane poprawnie.
W moim przypadku chciałem zwrócić wartość null, a nigdy domyślną wartość dowolnego możliwego typu wartości. GetValueOrDefault = zły. GetValueOrNull = dobra.
Użyłem słów „Null” i „Nullable”, aby rozróżnić typy referencyjne i typy wartości. A oto przykład kilku metod rozszerzenia, które napisałem, które uzupełniają metodę FirstOrDefault w klasie System.Linq.Enumerable.
źródło
Krótsza droga:
powrót
0
doint
, anull
dlaint?
źródło