Czytając to , dowiedziałem się, że można zezwolić metodzie na akceptowanie parametrów wielu typów, czyniąc ją metodą ogólną. W tym przykładzie poniższy kod jest używany z ograniczeniem typu, aby zapewnić, że „U” to IEnumerable<T>
.
public T DoSomething<U, T>(U arg) where U : IEnumerable<T>
{
return arg.First();
}
Znalazłem więcej kodu, który pozwolił na dodanie wielu ograniczeń typu, takich jak:
public void test<T>(string a, T arg) where T: ParentClass, ChildClass
{
//do something
}
Jednak ten kod wydaje się wymuszać, że arg
musi to być zarówno typ, jak ParentClass
i ChildClass
. Chcę tylko powiedzieć, że argument może być rodzajem ParentClass
lub ChildClass
w następujący sposób:
public void test<T>(string a, T arg) where T: string OR Exception
{
//do something
}
Twoja pomoc jest mile widziana jak zawsze!
c#
asp.net-mvc-3
types
Mansfield
źródło
źródło
where T : string
, ponieważstring
jest to klasa zapieczętowana . Jedyną przydatną rzeczą, jaką możesz zrobić, jest zdefiniowanie przeciążeń dlastring
iT : Exception
, jak wyjaśnił @ Botz3000 w jego odpowiedzi poniżej.arg
są metody zdefiniowane przezobject
- dlaczego więc po prostu nie usunąć typów generycznych z obrazu i utworzyć typarg
object
? Co zyskujesz?Odpowiedzi:
Nie jest możliwe. Możesz jednak zdefiniować przeciążenia dla określonych typów:
Jeśli są one częścią klasy ogólnej, będą preferowane w stosunku do ogólnej wersji metody.
źródło
or
związek sprawia, że rzeczy są zbyt ogólne, aby były przydatne. Chcesz mieć zrobić odbicie, aby dowiedzieć się, co zrobić, i to wszystko. (Fuj!).Odpowiedź Botza jest w 100% poprawna, oto krótkie wyjaśnienie:
Kiedy piszesz metodę (ogólną lub nie) i deklarujesz typy parametrów, które metoda przyjmuje, definiujesz kontrakt:
Jeśli spróbujesz podać więcej niż jeden typ na raz (przez posiadanie lub) lub spróbujesz sprawić, aby zwracał wartość, która może być więcej niż jednego typu, kontrakt stanie się rozmyty:
Problem polega na tym, że kiedy wchodzisz do metody, nie masz pojęcia, czy dali ci
IJumpRope
czyPiFactory
. Co więcej, kiedy korzystasz z metody (zakładając, że udało ci się ją magicznie skompilować), nie jesteś pewien, czy maszFisher
plikAbstractConcreteMixer
. Zasadniczo sprawia, że całość jest o wiele bardziej zagmatwana.Rozwiązanie twojego problemu jest jedną z dwóch możliwości:
Zdefiniuj więcej niż jedną metodę, która definiuje każdą możliwą transformację, zachowanie lub cokolwiek innego. To odpowiedź Botza. W świecie programowania nazywa się to przeciążaniem metody.
Zdefiniuj klasę bazową lub interfejs, który wie, jak zrobić wszystko, czego potrzebujesz dla metody i niech jedna metoda przyjmuje tylko ten typ. Może to obejmować zamknięcie
string
iException
w małej klasie, aby zdefiniować, w jaki sposób planujesz odwzorować je na implementację, ale wtedy wszystko jest bardzo jasne i łatwe do odczytania. Mógłbym przyjść za cztery lata i przeczytać twój kod i łatwo zrozumieć, co się dzieje.To, który wybierzesz, zależy od tego, jak skomplikowany byłby wybór 1 i 2 i jak musi być rozszerzalny.
Więc w twojej konkretnej sytuacji wyobrażam sobie, że po prostu wyciągasz wiadomość lub coś z wyjątku:
Teraz wszystko, czego potrzebujesz, to metody, które przekształcają a
string
i anException
w IHasMessage. Bardzo łatwe.źródło
Jeśli ChildClass oznacza, że pochodzi z ParentClass, możesz po prostu napisać następujący tekst, aby zaakceptować zarówno ParentClass, jak i ChildClass;
Z drugiej strony, jeśli chcesz użyć dwóch różnych typów bez relacji dziedziczenia między nimi, powinieneś rozważyć typy implementujące ten sam interfejs;
wtedy możesz napisać swoją ogólną funkcję jako;
źródło
Tak stare, jak to pytanie, wciąż otrzymuję losowe głosy za moim wyjaśnieniem powyżej. Wyjaśnienie nadal jest w porządku i tak jest, ale odpowiem po raz drugi typem, który służył mi dobrze jako substytut typów unii (silnie wpisana odpowiedź na pytanie, które nie jest bezpośrednio obsługiwane przez C #, jak jest ).
Powyższe klasy reprezentuje typ, który może być albo TP lub Ta. Możesz go użyć jako takiego (typy odnoszą się do mojej oryginalnej odpowiedzi):
Ważne notatki:
IsPrimary
najpierw, otrzymasz błędy czasu wykonania .IsNeither
IsPrimary
lubIsAlternate
.Primary
iAlternate
Either
wszędzie tam, gdzie jest to oczekiwane. Jeśli zrobić zdaćEither
gdzieTA
alboTP
ma, aleEither
zawiera niewłaściwy typ wartości dostaniesz błąd wykonania.Zwykle używam tego, gdy chcę, aby metoda zwracała wynik lub błąd. Naprawdę oczyszcza ten kod stylu. Bardzo rzadko ( rzadko ) używam tego jako zamiennika przeciążeń metod. Realistycznie jest to bardzo kiepski substytut takiego przeciążenia.
źródło