Comment passer des types anonymes comme paramètres?

Comment passer des types anonymes comme paramètres à d'autres fonctions? Prenons l'exemple suivant:

var query = from employee in employees select new { Name = employee.Name, Id = employee.Id };
LogEmployees(query);

variable query ici n'a pas de type fort. Comment définir ma fonction Log employees pour l'accepter?

public void LogEmployees (? list)
{
    foreach (? item in list)
    {

    }

}

en d'autres termes, Que dois-je utiliser à la place des marques ? .

108
demandé sur Shog9 2011-07-08 17:03:10

10 réponses

je pense que vous devriez faire un cours pour ce type anonyme. Ce serait la chose la plus sensée à faire à mon avis. Mais si vous ne voulez vraiment pas, vous pouvez utiliser la dynamique:

public void LogEmployees (IEnumerable<dynamic> list)
{
    foreach (dynamic item in list)
    {
        string name = item.Name;
        int id = item.Id;
    }
}

notez que c'est pas fortement tapé, donc si, par exemple, le nom change en EmployeeName, vous ne saurez pas qu'il y a un problème jusqu'à l'exécution.

134
répondu Tim S. 2011-07-08 13:18:37

Vous pouvez le faire comme ceci:

public void LogEmployees<T>(List<T> list) // Or IEnumerable<T> list
{
    foreach (T item in list)
    {

    }
}

... mais vous n'obtiendrez pas beaucoup à faire avec chaque élément. Vous pouvez appeler ToString, mais vous ne pourrez pas utiliser (dire) Name et Id directement.

34
répondu Jon Skeet 2011-07-08 13:21:57

Malheureusement, ce que vous essayez de faire est impossible. Sous le capot, la variable de requête est tapée pour être un IEnumerable d'un type anonyme. Les noms de type anonymes ne peuvent pas être représentés dans le code d'utilisateur, il n'y a donc aucun moyen de les transformer en paramètre d'entrée d'une fonction.

Votre meilleur pari est de créer un type et de l'utiliser comme retour de la requête, puis le passer à la fonction. Par exemple,

struct Data {
  public string ColumnName; 
}

var query = (from name in some.Table
            select new Data { ColumnName = name });
MethodOp(query);
...
MethodOp(IEnumerable<Data> enumerable);

dans ce cas bien que vous ne sélectionniez qu'un seul champ, il peut donc être plus facile de le sélectionner directement. Ceci fera que la requête sera tapée comme un IEnumerable du type de champ. Dans ce cas, le nom de colonne.

var query = (from name in some.Table select name);  // IEnumerable<string>
17
répondu JaredPar 2012-02-17 12:09:18

normalement, vous faites cela avec des génériques, par exemple:

MapEntToObj<T>(IQueryable<T> query) {...}

le compilateur devrait alors inférer le T quand vous appelez MapEntToObj(query) . Pas tout à fait sûr de ce que vous voulez faire à l'intérieur de la méthode, donc je ne peux pas dire si c'est utile... le problème est que dans MapEntToObj vous ne pouvez toujours pas nommer le T - vous pouvez soit:

  • appeler d'autres méthodes génériques avec T
  • utilisation réflexion sur T faire des choses

mais à part cela, il est assez difficile de manipuler les types anonymes-notamment parce qu'ils sont immuables; - p

un autre truc (quand extraire données) est de passer aussi un sélecteur - i.e. quelque chose comme:

Foo<TSource, TValue>(IEnumerable<TSource> source,
        Func<TSource,string> name) {
    foreach(TSource item in source) Console.WriteLine(name(item));
}
...
Foo(query, x=>x.Title);
7
répondu Marc Gravell 2009-04-22 05:32:54

vous pouvez utiliser des génériques avec le truc suivant (casting au type anonyme):

public void LogEmployees<T>(IEnumerable<T> list)
{
    foreach (T item in list)
    {
        var typedItem = Cast(item, new { Name = "", Id = 0 });
        // now you can use typedItem.Name, etc.
    }
}

static T Cast<T>(object obj, T type)
{
    return (T)obj;
}
6
répondu Stanislav Basovník 2011-07-08 13:25:07

"dynamique" peut également être utilisé à cette fin.

var anonymousType = new { Id = 1, Name = "A" };

var anonymousTypes = new[] { new { Id = 1, Name = "A" }, new { Id = 2, Name = "B" };

private void DisplayAnonymousType(dynamic anonymousType)
{
}

private void DisplayAnonymousTypes(IEnumerable<dynamic> anonymousTypes)
{
   foreach (var info in anonymousTypes)
   {

   }
}
4
répondu Dinesh Kumar P 2014-05-22 06:18:17

au lieu de passer un type anonyme, passer une liste d'un type dynamique:

  1. var dynamicResult = anonymousQueryResult.ToList<dynamic>();
  2. méthode signature: DoSomething(List<dynamic> _dynamicResult)
  3. méthode D'appel: DoSomething(dynamicResult);
  4. fait.

merci à Petar Ivanov !

1
répondu usefulBee 2017-05-23 12:03:08

si vous savez que vos résultats implémentent une certaine interface, vous pouvez utiliser l'interface comme type de données:

public void LogEmployees<T>(IEnumerable<T> list)
{
    foreach (T item in list)
    {

    }
}
0
répondu Alex 2011-07-08 13:09:58

j'utiliserais IEnumerable<object> comme type pour l'argument. Cependant pas un grand gain pour la distribution explicite inévitable. Cheers

0
répondu Mario Vernari 2011-07-08 13:13:10