2012-08-06 16 views
5

Mam następujące metody pomocnika:Nie boks lub rodzaj konwersji parametr parametr typu rodzajowego

public static T CreateRequest<T>() 
    where T : Request, new() 
{ 
    T request = new T(); 
    // ... 
    // Assign default values, etc. 
    // ... 
    return request; 
} 

chcę użyć tej metody od wewnątrz innej metody w innym pomocnika:

public T Map<F, T>(F value, T toValue) 
    where T : new() 
    where F : new() 
{ 
    if (typeof(T).BaseType.FullName == "MyNamespace.Request") 
    { 
     toValue = MyExtensions.CreateRequest<T>(); 
    } 
    else 
    { 
     toValue = new T(); 
    } 
} 

Ale wtedy pojawia się błąd:

The type 'T' cannot be used as type parameter 'T' in the generic type or method 'MyExtensions.CreateRequest()'. There is no boxing conversion or type parameter conversion from 'T' to 'MyNamespace.Request'.

Czy istnieje sposób, aby rzucić typ "T", tak aby CreateRequest woul d używać go bez problemów?

EDIT:

wiem, że mogę zrobić dwie rzeczy:

  • poluzować ograniczeń createRequest lub
  • dokręcić contraints na mapie.

Ale nie mogę wykonać pierwszego, ponieważ w CreateRequest I właściwości użytkownika klasy Request, i nie mogę zrobić drugiego, ponieważ używam innych typów (które nie dziedziczą z żądania) z mapą funkcjonować.

+0

to znaczy: „albo albo żadna” –

Odpowiedz

4

W tym scenariuszu musisz poluzować rodzajowe ograniczeń CreateRequest.

public static T CreateRequest<T>() 
    where T : new() 
{ 
    if(!typeof(Request).IsAssignableFrom(typeof(T))) 
     throw new ArgumentException(); 

    var result = new T(); 
    Request request = (Request)(object)result; 
    // ... 
    // Assign default values, etc. 
    // ... 
    return result ; 
} 

To może być bolesne, ponieważ utracono weryfikację czasu kompilacji tego parametru.

Jeśli chcesz użyć innej metody niż CreateRequest, utwórz nietypowe przeciążenie tylko w tym scenariuszu.

public static object CreateRequest(Type requestType) 
{ 
    if(!typeof(Request).IsAssignableFrom(requestType)) 
     throw new ArgumentException(); 

    var result = Activator.CreateInstance(requestType); 
    Request request = (Request)result; 
    // ... 
    // Assign default values, etc. 
    // ... 
    return result ; 
} 
+0

dlaczego ta podwójna obsada jest potrzebna? '(Request) (object) result;' –

+0

ładnie złap z '.IsAssignableFrom'! o wiele lepsze niż porównanie stringów! –

+0

Podwójna obsada jest dla kompilatora, aby powiedzieć mu, że wiesz, co robisz i bierzesz za to odpowiedzialność. Bez niego to nie zadziała, a powyższe gwarantuje, że to zadziała. – Rafal

3

Użytkownik zadeklarował, że typ metody T to Request w CreateRequest; z drugiej strony, w metodzie Map nie masz takiego ograniczenia. Spróbuj zmienić deklarację z Map do:

public T Map<F, T>(F value, T toValue) 
where T : Request, new() 
where F : new() 
+0

Problem jest używać funkcji mapa z typów, które nie dziedziczą z Życzenie, więc nie mogę ustawić contraint. –

+0

Następnie można spróbować usunąć ograniczenie żądania z funkcji CreateRequest. – daryal

Powiązane problemy