Generics w C#, używając typu zmiennej jako parametru [duplikat]
To pytanie ma już odpowiedź tutaj:
- Jak użyć reflection, aby wywołać metodę generyczną? 7 odpowiedzi
I have a generic method
bool DoesEntityExist<T>(Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
Jak używać metody w następujący sposób:
Type t = entity.GetType();
DoesEntityExist<t>(entityGuid, transaction);
Ciągle otrzymuję błąd kompilacji:
Nazwa typu lub przestrzeni nazw " t " może nie można znaleźć (są brakuje Ci dyrektywa czy odniesienie do Zgromadzenia?)
DoesEntityExist<MyType>(entityGuid, transaction);
Działa doskonale, ale nie chcę używać dyrektywy if do wywoływania metody z osobną nazwą typu za każdym razem.
4 answers
Chodzi o to, aby zapewnić czas kompilacji bezpieczeństwo typu - co oznacza, że typy muszą być znane w czasie kompilacji.
Ty możesz wywoływać metody generyczne z typami znanymi tylko w czasie wykonywania, ale musisz użyć reflection:
// For non-public methods, you'll need to specify binding flags too
MethodInfo method = GetType().GetMethod("DoesEntityExist")
.MakeGenericMethod(new Type[] { t });
method.Invoke(this, new object[] { entityGuid, transaction });
Ick.
Czy możesz zamiast tego uczynić metodę wywołującą i przekazać parametr type jako argument type, przesuwając decyzję o jeden poziom wyżej w górę stosu?
If you could give us more informacje o tym, co robisz, to by pomogło. Czasami może być konieczne użycie odbicia jak powyżej, ale jeśli wybierzesz odpowiedni punkt, aby to zrobić, możesz upewnić się, że musisz to zrobić tylko raz i pozwolić wszystkim poniżej tego punktu używać parametru type w normalny sposób.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-11 06:49:53
Jednym ze sposobów obejścia tego jest użycie ukrytego odlewania:
bool DoesEntityExist<T>(T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
Nazywając to tak:
DoesEntityExist(entity, entityGuid, transaction);
Idąc o krok dalej, możesz przekształcić ją w metodę rozszerzenia (będzie ona musiała być zadeklarowana w klasie statycznej):
static bool DoesEntityExist<T>(this T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
Wywołanie Tak:
entity.DoesEntityExist(entityGuid, transaction);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-21 08:45:09
Nie jestem pewien, czy dobrze rozumiem twoje pytanie, ale możesz napisać swój kod w ten sposób:
bool DoesEntityExist<T>(T instance, ....)
Możesz wywołać metodę w następujący sposób:
DoesEntityExist(myTypeInstance, ...)
W ten sposób nie musisz jawnie zapisywać typu, framework automatycznie przejmie Typ od instancji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-21 08:44:15
Nie możesz tego użyć w sposób, w jaki opisujesz. Chodzi o to, że chociaż możesz nie znać ich w "czasie kodowania", kompilator musi być w stanie je rozwiązać w czasie kompilacji. Dlaczego? Ponieważ pod maską kompilator odejdzie i utworzy nowy typ (czasami nazywany zamkniętym typem generycznym) dla każdego innego użycia "otwartego" typu generycznego.
Innymi słowy, po kompilacji,
DoesEntityExist<int>
Jest innym typem
DoesEntityExist<string>
Oto jak kompilator jest w stanie zapewnić bezpieczeństwo typu compile-time.
Dla scenariusza, który opisujesz, powinieneś przekazać Typ jako argument, który można zbadać w czasie wykonywania.
Inną opcją, jak wspomniano w innych odpowiedziach, jest użycie refleksji do tworzenia typu zamkniętego z typu otwartego, chociaż prawdopodobnie jest to zalecane w cokolwiek innego niż ekstremalne scenariusze niszowe, powiedziałbym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-21 08:42:34