2010-01-08 2 views
1

Je reçois l'erreur du compilateur suivantpropriété générique Cast de type T à un type d'héritage connu

Impossible de convertir le type 'T' à 'ProjectReportingHandler'

pour la ligne

var projectReport = (ProjectReportingHandler)result.Report; 

en essayant de compiler:

public abstract class ReportingHandler 
{ 
    // Report stuff 
} 

public abstract class ProjectReportingHandler: ReportingHandler 
{ 
    // Report stuff 
    // Project specific report stuff 
} 

public class ReportInstance<T> 
    where T : ReportingHandler 
{ 
    public T Report { get; private set; } 
} 

public class ReportLibraryEntry<T> 
     where T : ReportingHandler 
{ 
    public ReportInstance<T> Create() 
    { 
     ReportInstance<T> result = new ReportInstance<T>(); 

     if (result.Report is ProjectReportingHandler) 
     { 
      var projectReport = (ProjectReportingHandler)result.Report; 
      // do stuff with project reports 
     } 

     return result; 
    } 
} 

Des idées comment transformer la propriété de type générique liée result.Report en ProjectReportingHandler?

j'aurais pensé que le where T : ReportingHandler aurait assuré que cela était possible :(

EDIT: Je semblent obtenir quelques réponses qui disent ma réponse acceptée est incorrecte Il fonctionne, et je mis en œuvre comme suit.:

public ReportInstance<T> Create() 
{ 
    ReportInstance<T> result = new ReportInstance<T>(); 

    ReportingHandler report = result.Report; 
    if (report is ProjectReportingHandler) 
    { 
     var projectReport = (ProjectReportingHandler)report; 
     // do stuff with project reports 
    } 

    return result; 
} 

Pourquoi les voix vers le bas pour une réponse qui a fonctionné :(

Répondre

0

Vous pouvez "tricher" en premier résultat de la distribution. Rapportez à un objet, puis à un ProjectReportingHandler.

+0

Cela peut jeter un 'InvalidCastException'. – SLaks

+0

Super, merci! On dirait que cela devrait être un truc de compilateur intégré, car je ne vois pas pourquoi empêcher cela avec l'erreur susmentionnée est utile: s – Codesleuth

+0

@SLaks: Même quand j'ai le code dans le 'if (result.Report est ProjectReportingHandler) 'bloquer? – Codesleuth

3

T:? ReporingHandler ne garantit pas que que la conversion est possible Juste parce qu'un ProjectReportingHandler est un ReportingHandler ne me pas. un contraire est vrai.

4

where T : ReportingHandler n'est pas suffisant.
Que devrait-il se passer si T est un autre type qui hérite ReportingHandler mais pas ProjectReportingHandler? Si vous êtes sûr que T héritera toujours de ProjectReportingHandler, vous pouvez modifier la contrainte where T : ProjectReportingHandler.

Si vous voulez vraiment faire les choses comme vous le faites maintenant, vous devez d'abord jeter à ReportingHandler, comme ceci:

var projectReport = ((ReportingHandler)result.Report) as ProjectReportingHandler; 

Si T ne possèdes pas ProjectReportingHandler, projectReport sera null.

+0

Mais j'ai la ligne 'if (result.Report is ProjectReportingHandler)' qui sera la condition contenant ... Je ne vois pas pourquoi ce ne serait pas toujours un 'ProjectReportingHandler' si je vérifie d'abord? – Codesleuth

+0

Ca va être un peu plus lent, puisqu'il va lancer deux fois. Il est plus rapide d'appeler 'as' et de vérifier si c'est' null'. – SLaks

+0

Je vois votre point, mais l'amélioration de la vitesse est une différence mineure :) En outre, êtes-vous sûr que l'IL est très différent? Serait intéressant de voir. – Codesleuth

1

Comment l'utilisation as:

 ReportInstance<T> result = new ReportInstance<T>(); 
     var projectReport = result.Report as ProjectReportingHandler; 
     if (projectReport != null) 
     { 
      //do stuff 
     } 
+0

En fait, cette solution de contournement est meilleure que la réponse acceptée car "tricher" fait 2 transtypages, alors que "as" utilise 1 transtypage. –

Questions connexes