2009-02-27 5 views
1

Comment spécifier la signature Func pour les objets anonymes?Comment spécifier .NET Type de retour d'objet anonyme dans Linq en utilisant Func <T,Q>?

new Func<DataSet, **IEnumerable<int>>** 

J'ai un problème avec le type de retour où je l'ai spécifié comme IEnumerable <> dans la déclaration Func

erreur que je reçois de l'expression est

Impossible de convertir l'expression type 'System.Collections.Generic.IEnumerable < {ParentNodeId: int}>' pour renvoyer ype 'System.Collections.Generic.IEnumerable'

Comment puis-je spécifier IEnumerable < {ParentNodeId: int}> dans func? Par ailleurs, j'aurais pu utiliser le code commenté "query" et en avoir terminé avec. Mais voulait être plus expressif et essayer quelque chose de nouveau après avoir regardé cette réponse Why doesn't C# have lexically nested functions?

EDIT: Résultat final

public int GetCachedRootNodeId(IList<int> fromNodeIds, int forNodeId) 
    { 
     var result = forNodeId; 

     const string spName = "spFetchAllParentNodeIDs"; 
     using (var ds = _df.ExecuteDatasetParamArray(_ConnectionString, spName, forNodeId)) 
     { 
      if (DataAccessUtil.DataSetIsEmpty(ds)) return result; 

      var orderParentNodeIDByLevelDesc = new Func<DataSet, IEnumerable<int>>(resultSet => 
       from DataRow row in DataAccessUtil.GetFirstTableRows(resultSet) 
       orderby DataAccessUtil.GetInt32(row, "Level") descending 
       select DataAccessUtil.GetInt32(row, "ParentNodeID")); 

      foreach (var parentNodeId in orderParentNodeIDByLevelDesc(ds)) 
      { 
       if (fromNodeIds.Contains(parentNodeId)) 
        return parentNodeId; 
      } 
     } 

     return result; 
    } 

Répondre

2

Dans ce cas tout ce que vous voulez vraiment est comme int ...donc il suffit de changer votre sélection pour:

select DataAccessUtil.GetInt32(row, "ParentNodeID")); 

Et changer votre foreach à:

foreach (var nodeInfo in orderByLevelDesc(ds)) 
{ 
    if (fromNodeIds.Contains(nodeInfo)) 
     return nodeInfo; 
} 
+0

Ha !, c'était mon intention originale Merci – Sung

+0

La réponse de Jon Skeet est géniale si quelqu'un a vraiment besoin d'une classe d'anony multiproperty mais dans ce cas, c'est juste un int! – TheSoftwareJedi

+0

J'aurais choisi la réponse de Jon Skeet comme réponse a été que je retourne plusieurs propriétés comme vous l'avez mentionné. – Sung

2

Il n'y a aucun moyen de spécifier les types anonymes dans les déclarations. Vous devez créer une classe nommée pour cela. Jon Skeet a un related blog entry sur ce problème.

+0

Je n'ai en effet une entrée de blog, mais je ne pense pas que nous devons désespérer cette fois :) En fait –

+0

J'ai apprécié quand je l'ai lu. Je cherchais juste un endroit pour partager;) –

+0

Sentez-vous libre alors :) –

3

est ici une idée - appeler une méthode statique et laisser l'inférence de type faire:

public static Func<T, TResult> FuncOf(Func<T, TResult> func) 
{ 
    return func; 
} 

alors simplement l'appeler:

var orderByLevelDesc = FuncOf(resultSet => 
    from DataRow row in DataAccessUtil.GetFirstTableRows(resultSet) 
    orderby DataAccessUtil.GetInt32(row, "Level") descending 
    select new { ParentNodeId = DataAccessUtil.GetInt32(row, "ParentNodeID") 
    }); 

Fondamentalement, il vous suffit de la partie « Func » pour dire compilateur qu'il a besoin de convertir l'expression lambda en un délégué au lieu d'une expression, et le type du délégué. Il devrait être capable de travailler le type donné la signature de FuncOf.

Cela vaut la peine d'essayer, quoi qu'il en soit.

Je devrais dire, en passant, que je trouve votre version commentée plus facile à comprendre. Pourquoi introduire une fonction supplémentaire? Ou était votre plan à pas avoir cela comme une variable locale (ce qui aurait plus de sens, mais alors vous ne pouviez pas utiliser var)? Ou peut-être une variable locale déclarée en dehors de la boucle au lieu de l'intérieur?

+0

Cela a fonctionné comme un charme. Je devais juste changer la signature de FuncOf en "public static Func FuncOf (Func func)". Et aussi lors de l'appel, "FuncOf (resultSet" à "FuncOf ((DataSet resultSet" depuis "GetFirstTableRows" méthode attend un DataSet et il n'a pas été inféré – Sung

+0

Pourquoi faire si compliqué? Voir ma réponse ci-dessus – TheSoftwareJedi

+0

@TheSoftwareJedi: J'essayais d'aborder la question derrière la situation actuelle plutôt que de simplement résoudre ce cas particulier (que je n'ai pas examiné en détail, je dois l'admettre.) Les deux réponses utiles de différentes manières :) –

Questions connexes