Próbuję utworzyć ogólne rozszerzenie, które używa „TryParse”, aby sprawdzić, czy łańcuch jest danego typu:
public static bool Is<T>(this string input)
{
T notUsed;
return T.TryParse(input, out notUsed);
}
to się nie skompiluje, ponieważ nie może rozwiązać symbolu „TryParse”
Jak rozumiem, „TryParse” nie jest częścią żadnego interfejsu.
Czy to w ogóle można zrobić?
Aktualizacja:
Korzystając z poniższych odpowiedzi, wymyśliłem:
public static bool Is<T>(this string input)
{
try
{
TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
}
catch
{
return false;
}
return true;
}
Działa całkiem dobrze, ale myślę, że stosowanie wyjątków w ten sposób nie wydaje mi się właściwe.
Aktualizacja 2:
Zmodyfikowano tak, aby podawał typ, zamiast używać ogólnych:
public static bool Is(this string input, Type targetType)
{
try
{
TypeDescriptor.GetConverter(targetType).ConvertFromString(input);
return true;
}
catch
{
return false;
}
}
protected Boolean TryParse<T>(Object value, out T result) { result = default(T); var convertor = TypeDescriptor.GetConverter(typeof(T)); if (convertor == null || !convertor.IsValid(value)) { return false; } result = (T)convertor.ConvertFrom(value); return true; }
ConvertFrom(value)
metodę wtry-catch
blok, aby uchwycić wyjątkiOdpowiedzi:
Powinieneś użyć klasy TypeDescriptor :
źródło
Ostatnio również wymagałem ogólnego tryParse. Oto, co wymyśliłem;
Zatem wystarczy po prostu zadzwonić w ten sposób:
źródło
T
z modułu obsługi i musimy wyraźnie określić,T
kiedy go wywołujemy. Jestem ciekawy, dlaczego to nie może wywnioskowaćT
?SomeMethod(TryParse<int>(DollarTextbox.Text, int.TryParse))
bez tworzenia zmiennej wyjściowej do przechwytywania wynikuint.TryParse
. Zgadzam się jednak z sentymentem Nicka, że funkcja wnioskuje o typie.Używanie try / catch do kontroli przepływu jest okropną polityką. Zgłoszenie wyjątku powoduje opóźnienia w wydajności podczas działania środowiska wykonawczego wokół tego wyjątku. Zamiast tego sprawdź poprawność danych przed konwersją.
źródło
converter != null
jest zawsze prawdziwe, więc można je usunąć z kodu.Jeśli korzystasz z TryParse, możesz użyć odbicia i zrobić to w następujący sposób:
źródło
Type.GetType(string.Format(...))
ztype.MakeByRefType()
.Używa konstruktora statycznego dla każdego typu ogólnego, więc musi wykonać kosztowną pracę tylko przy pierwszym wywołaniu danego typu. Obsługuje wszystkie typy w przestrzeni nazw systemu, które mają metody TryParse. Działa również z zerowymi wersjami każdej z nich (które są strukturami), z wyjątkiem wyliczeń.
źródło
Co powiesz na coś takiego?
http://madskristensen.net/post/Universal-data-type-checker.aspx ( Archiwum )
Można to łatwo przekonwertować na metodę ogólną.
źródło
catch { }
. Jednak w tym przypadku nie ma alternatywy, ponieważ .NETBaseNumberConverter
rzucaException
klasę bazową w przypadku błędu konwersji. To bardzo niefortunne. W rzeczywistości jest jeszcze kilka miejsc, w których rzucono ten podstawowy typ. Mamy nadzieję, że Microsoft naprawi je w przyszłej wersji frameworka.Nie możesz tego zrobić na typach ogólnych.
Co możesz zrobić, to utworzyć interfejs ITryParsable i użyć go do niestandardowych typów, które implementują ten interfejs.
Myślę jednak, że zamierzasz używać tego z podstawowymi typami, takimi jak
int
iDateTime
. Nie można zmienić tych typów w celu wdrożenia nowych interfejsów.źródło
dynamic
słowem kluczowym, ponieważ nie będzie działać na pisaniu statycznym. Możesz utworzyć własny obiekt dynamiczny, który może to obsłużyć, ale nie jest to ustawienie domyślne.Zainspirowany rozwiązaniem opublikowanym tutaj przez Charliego Browna, stworzyłem ogólny TryParse za pomocą odbicia, które opcjonalnie wypisuje przeanalizowaną wartość:
Można to nazwać w ten sposób:
Aktualizacja:
Również dzięki rozwiązaniu YotaXP, które bardzo mi się podoba, stworzyłem wersję, która nie korzysta z metod rozszerzeń, ale wciąż ma singleton, co minimalizuje potrzebę refleksji:
Nazwij to tak:
źródło
Trochę późno na imprezę, ale oto co wymyśliłem. Bez wyjątków, jednorazowe odbicie (według typu).
Wymagana jest dodatkowa klasa, ponieważ metody rozszerzenia nie są dozwolone w klasach ogólnych. Umożliwia to proste użycie, jak pokazano poniżej, i odbija odbicie tylko przy pierwszym użyciu typu.
źródło
Oto kolejna opcja.
Napisałem klasę, która ułatwia zarejestrowanie dowolnej liczby programów
TryParse
obsługi. Pozwala mi to zrobić:Zostaję
42
wydrukowany na konsoli.Klasa jest:
źródło
Kiedy chciałem zrobić dokładnie to dokładnie, musiałem to zrealizować w sposób trudny, biorąc pod uwagę refleksję. Biorąc pod uwagę
T
, zastanów siętypeof(T)
i poszukaj metodyTryParse
lubParse
metody, wywołując ją, jeśli ją znalazłeś.źródło
To jest moja próba. Zrobiłem to jako „ćwiczenie”. Próbowałem uczynić to tak podobnym do użycia jak istniejące „ Convert.ToX () ” itp. Ale ta metoda jest metodą rozszerzenia:
źródło
TypeConverter.ConvertFrom()
tym jest to, że klasa źródłowa musi zapewniać konwersję typu, co ogólnie oznacza, że nie można obsługiwać konwersji na typy niestandardowe.Jak powiedziałeś,
TryParse
nie jest częścią interfejsu. To również nie jest członkiem danej klasy bazowej, ponieważ jest to faktyczniestatic
istatic
funkcje nie mogą byćvirtual
. Tak więc kompilator nie ma możliwości zapewnienia, żeT
faktycznie ma on członka o nazwieTryParse
, więc to nie działa.Jak powiedział @Mark, możesz stworzyć własny interfejs i używać niestandardowych typów, ale nie masz szczęścia do wbudowanych typów.
źródło
źródło
Jest to kwestia „ogólnych ograniczeń”. Ponieważ nie masz określonego interfejsu, utkniesz, chyba że podążasz za sugestiami z poprzedniej odpowiedzi.
Aby uzyskać dokumentację na ten temat, sprawdź następujący link:
http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx
Pokazuje, jak korzystać z tych ograniczeń i powinien dać ci więcej wskazówek.
źródło
Pożyczone od http://blogs.msdn.com/b/davidebb/archive/2009/10/23/using-c-dynamic-to-call-static-members.aspx
postępując zgodnie z tym odniesieniem: Jak wywołać metodę statyczną w C # 4.0 z typem dynamicznym?
I użyj go w następujący sposób:
źródło
Udało mi się zdobyć coś, co tak działa
Oto mój kod
StaticMembersDynamicWrapper został zaadaptowany z artykułu Davida Ebbo ( zgłaszał wyjątek AmbiguousMatchException )
źródło
źródło
Z
TypeDescriptor
wykorzystaniem klasy wTryParse
podobny sposób:źródło
Korzystając z powyższych informacji, opracowałem to. Przekształci obiekt bezpośrednio, jest to możliwe, w przeciwnym razie przekształci obiekt w ciąg i wywoła metodę TryParse dla pożądanego typu obiektu.
Metody buforuję w słowniku, gdy każda z nich jest napotkana, aby zmniejszyć obciążenie pobierania metody.
Możliwe jest sprawdzenie, czy obiekt można bezpośrednio przekonwertować na typ docelowy, co dodatkowo zmniejszy część konwersji ciągu. Ale na razie to pominę.
źródło
Zebrałem tu kilka pomysłów i otrzymałem bardzo krótkie rozwiązanie.
Jest to metoda rozszerzenia ciągu
Zrobiłem to z takim samym drukiem stóp jak metody TryParse na typach numerycznych
''
źródło
T.TryParse ... dlaczego?
Nie widzę żadnej korzyści z takiej ogólnej
TryParse
funkcji. Istnieje zbyt wiele różnych strategii analizowania i konwertowania danych między różnymi typami, z możliwym konfliktowym zachowaniem. Skąd ta funkcja mogła wiedzieć, którą wybrać strategię bez kontekstu?Convert.ChangeType
. Ten interfejs API można dostosować w czasie wykonywania. Czy twoja funkcja wymaga domyślnego zachowania lub pozwala na dostosowanie?źródło
Wersja do pobierania potomków z XDocument.
źródło