2009-11-12 8 views
20

Brakuje mi tutaj pewnej sztuczki i nie mogę uwierzyć, że nigdy tego nie robiłem. Jednak w jaki sposób mogę rzucić typ ogólny za pomocą słowa kluczowego as?Rzut typem ogólnym "jako T" podczas wymuszania typu T

[Serializable] 
public abstract class SessionManager<T> where T : ISessionManager 
{ 

    protected SessionManager() { } 

    public static T GetInstance(HttpSessionState session) 
    { 

     // Ensure there is a session Id 
     if (UniqueId == null) 
     { 
      UniqueId = Guid.NewGuid().ToString(); 
     } 

     // Get the object from session 
     T manager = session[UniqueId] as T; 
     if (manager == null) 
     { 
      manager = Activator.CreateInstance<T>(); 
      session[UniqueId] = manager; 
     } 

     return manager; 

    } 

    protected static string UniqueId = null; 

} 

Linia T manager = session[UniqueId] as T; wyrzuca następujący błąd:

The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint

Teraz myślę zrozumieć przyczynę tego; Nie powiedziałem fizycznie kompilatorowi, że T jest klasą. Jeśli mogę wymienić:

public abstract class SessionManager<T> where T : ISessionManager 

z

public abstract class SessionManager<T> where T : class 

... wtedy kod buduje pomyślnie.

Ale moje pytanie jest w ten sposób; jak mogę mieć egzekwowanie zarówno klasy, jak i menedżera ISessionManager w typie ogólnym? Mam nadzieję, że jest na to bardzo prosta odpowiedź.

EDIT: Wystarczy dodać próbowałem: where T : ISessionManager, class, okazuje się, że nie czytał mój błąd kompilatora prawidłowo. Wystarczy, że samo ustawienie klasy przed ISessionManager rozwiązuje problem. Błąd, którego nie przeczytałem:

"The 'class' or 'struct' constraint must come before any other constraints".

Głupi moment.

+2

BTW, nie należy używać '' CreateInstance tutaj. Powinieneś dodać ograniczenie 'new()' i po prostu użyć 'new T()' w kodzie. –

+0

Nigdy tego nie wiedziałem! Dzięki. – GenericTypeTea

Odpowiedz

37
... where T : class, ISessionManager 

W przypadku, gdy chcesz użyć gdzie keyword na metodach Oto przykład, który również używa rodzajowych

public void store<T>(T value, String key) 
    { 
     Session[key] = value; 
    } 

    public T retrieve<T>(String key) where T:class 
    { 
     return Session[key] as T ; 
    } 
+0

Ar **. Pisałem gdzie T: ISessionManager, klasa! – GenericTypeTea

+7

To nauczy mnie poprawnie odczytać błędy kompilatora. – GenericTypeTea

15
where T : class, ISessionManager 

można pójść jeszcze dalej

where T : class, ISessionManager, new() 

Będzie wymusić klasę inną niż abstrakcyjna z parametrowym ctor, który zostanie przekazany jako T

4

Przeczytaj na Constraints on Type Parameters in C#.

W tym konkretnym przypadku, należy upewnić się, że T jest klasa:

public abstract class SessionManager<T> 
    where T : class, ISessionManager 
+3

To nie będzie budować. ;) klasa musi być pierwsza. Ponadto wszystkie ograniczenia dla określonego typu muszą być określone w jednym miejscu gdzie klauzula ... – GenericTypeTea

+0

Masz rację, nie pamiętam składni, naprawione. –

+0

+1 do aktualizacji. – GenericTypeTea

Powiązane problemy