2009-11-07 6 views
2

Je ne pense même pas avoir la question correcte car je ne fais que commencer avec les génériques et mes connaissances ne sont pas très bonnes.Comment retourner une liste générique?

Dire que j'ai la méthode suivante:

public class Wrapper 
{ 
    public List<TInfoType> GetInfo<TInfoType>(Array data, EdmCmd edmCmd) 
    { 
     switch (edmCmd.meCmdType) 
     { 
     case EdmCmdType.EdmCmd_PostAdd: 
      List<EdmCmdPostAddInfo> info = new List<EdmCmdPostAddInfo>(); 
      foreach (EdmCmdData item in data) 
      { 
       info.Add(new EdmCmdPostAddInfo(item.mlObjectID1, item.mlObjectID2, item.mbsStrData1, item.mlLongData1)); 
      } 
      return info; 
      break;     
     default: 
      break; 
     } 
    } 
} 

Et je voudrais appeler la méthode comme:

List<EdmCmdPostAddInfo> info = wrapper.GetInfo<EdmCmdPostAddInfo>(data, edmCmd) 

Quelle est la bonne façon de le faire? Je reçois l'erreur:

Cannot implicitly convert type 'System.Collections.Generic.List<EPDM.Utils.EdmCmdPostAddInfo>' to 'System.Collections.Generic.List<TInfoType>' 

Je fais cela parce que le struct EdmCmd qui est passé à la méthode a plusieurs membres qui sont génériquement désignés. Il est difficile de se souvenir de ce que les membres représentent pour chaque CmdType, donc je les entoure d'une structure plus significative.

+0

Pas tout à fait une réponse, mais je pense que vous rencontrez le problème, que les génériques sont invariants sous C# 3.0. Avec C# 4.0 qui compilerait: http://visualstudiomagazine.com/Articles/2009/05/01/Generic-Covariance-and-Contravariance-in-C-40.aspx?Page=1 –

Répondre

1

Le fait que vous référenciez explicitement un type dans votre méthode générique indique que vous avez des problèmes. Le compilateur ne peut pas savoir qu'un List<T> peut contenir un objet d'un certain type, sauf si ce type est T.

Alors créez votre liste comme ceci:

result = new List<T>(); 
foreach (EdmCmdData item in data) 
{ 
    object o = new EdmCmdPostAddInfo(item.mlObjectID1, item.mlObjectID2, item.mbsStrData1, item.mlLongData1) 
    result.Add((T)s); 
} 
return result; 

Cela lancera une InvalidCastException lors de l'exécution si vous invoquez la méthode avec le mauvais type, mais c'est un problème que vous devriez déjà avoir attendez.

0

Je pense que je vois ce que vous essayez de faire, et ce n'est pas vraiment possible de le faire comme vous le souhaitez dans C# 3 et la version précédente. Ceci est un feature of C# 4 though, mais vous devrez attendre quelques mois pour que cela devienne RTM.

+0

Donc, j'ai fondamentalement besoin de créer un Méthode GetInfo() pour chaque type que je veux retourner? Bummer. – ehcanadian

+0

Ou vous pouvez simplement retourner le type de base, puis sur la fonction appelante, filtrer le type que vous voulez en utilisant la méthode d'extension .OfType () (Je pense que c'est dans le système.Linq) –

2

si vous utilisez

TInfoType[] data 

au lieu de

Array data 

comme paramètre, vous pouvez utiliser

List<TInfoType> info = new List<TInfoType>(); 

intead de

List<EdmCmdPostAddInfo> info = new List<EdmCmdPostAddInfo>();    

et vous n'avez pas besoin de faire le nouveau (à la place, vous utilisez simplement les objets transmis dans les données). J'espère que cela vous donne le point de départ.

+0

Je n'ai aucun contrôle sur ce qui est dans le tableau. Il est déjà rempli d'éléments EdmCmdData. (Je pense que je sais ce que vous dites.) – ehcanadian

1
public class Wrapper 
{ 
    public List<TInfoType> GetInfo<TInfoType>(Array data, EdmCmd edmCmd) 
    { 
     List<object> info = new List<object>(); 

     switch (edmCmd.meCmdType) 
     { 
     case EdmCmdType.EdmCmd_PostAdd: 
      foreach (EdmCmdData item in data) 
      { 
      info.Add(new EdmCmdPostAddInfo(item.mlObjectID1, item.mlObjectID2, item.mbsStrData1, item.mlLongData1)); 
      } 
      break;     
     default: 
      break; 
     } 

     return info.OfType<TInfoType>().ToList(); 
    } 
} 

En supposant que tous vos nouveaux ECMD * structures sont vraiment structs et non des classes avec une hiérarchie, vous pouvez créer une liste d'objets et lancez ce après avoir traité le passé dans le tableau.

Questions connexes