Jak mogę przekazać anonimowe typy jako parametry do innych funkcji? Rozważmy ten przykład:
var query = from employee in employees select new { Name = employee.Name, Id = employee.Id };
LogEmployees(query);
Zmienna query
tutaj nie ma silnego typu. Jak zdefiniować LogEmployees
funkcję, aby ją zaakceptować?
public void LogEmployees (? list)
{
foreach (? item in list)
{
}
}
Innymi słowy, czego powinienem używać zamiast ?
znaków.
c#
function
parameters
anonymous-types
Saeed Neamati
źródło
źródło
Odpowiedzi:
Myślę, że powinieneś stworzyć klasę dla tego anonimowego typu. Moim zdaniem byłoby to najbardziej sensowne. Ale jeśli naprawdę nie chcesz, możesz użyć dynamiki:
Zauważ, że nie jest to silnie wpisane, więc jeśli na przykład nazwa zmieni się na EmployeeName, nie będziesz wiedział, że wystąpił problem do czasu uruchomienia.
źródło
dynamic
użycie. Naprawdę mi się przydała. Dzięki :)Możesz to zrobić w ten sposób:
... ale nie będziesz miał wiele do zrobienia z każdym przedmiotem. Możesz wywołać ToString, ale nie będziesz mógł używać (powiedzmy)
Name
iId
bezpośrednio.źródło
where T : some type
na końcu pierwszej linii, aby zawęzić typ. W tym momencie jednak oczekiwanie określonego typu wspólnego interfejsu byłoby bardziej sensowne, gdybyśmy oczekiwali interfejsu. :)where T : some type
z typami anonimowymi, ponieważ nie implementują żadnego rodzaju interfejsu ...Niestety to, co próbujesz zrobić, jest niemożliwe. Pod maską zmienna zapytania jest wpisywana
IEnumerable
jako typu anonimowego. Nazwy typów anonimowych nie mogą być reprezentowane w kodzie użytkownika, dlatego nie ma możliwości uczynienia ich parametrem wejściowym dla funkcji.Najlepszym rozwiązaniem jest utworzenie typu i użycie go jako wyniku zapytania, a następnie przekazanie go do funkcji. Na przykład,
W tym przypadku jednak wybierasz tylko jedno pole, więc może być łatwiej po prostu wybrać pole bezpośrednio. Spowoduje to wpisanie zapytania jako
IEnumerable
typu pola. W tym przypadku nazwa kolumny.źródło
Equals
zmienia się zachowanie. To znaczy musisz to zaimplementować. (Wiedziałem o tej rozbieżności, ale mimo to udało mi się o tym zapomnieć podczas refaktoryzacji.)Nie można przekazać typu anonimowego do funkcji innej niż ogólna, chyba że typ parametru to
object
.Typy anonimowe są przeznaczone do krótkotrwałego użycia w ramach metody.
Z MSDN - typy anonimowe :
(podkreślenie moje)
Aktualizacja
Możesz użyć typów ogólnych, aby osiągnąć to, co chcesz:
źródło
object
- lubdynamic
; pobject
to nie to samo, co tworzenie metody generycznej w typie anonimowym, zgodnie z moją odpowiedzią.Zwykle robisz to za pomocą leków generycznych, na przykład:
Kompilator powinien następnie wywnioskować,
T
kiedy wywołujeszMapEntToObj(query)
. Nie jestem do końca pewien, co chcesz zrobić w metodzie, więc nie mogę powiedzieć, czy jest to przydatne ... Problem polega na tym, że w środkuMapEntToObj
nadal nie możesz nazwaćT
- możesz albo:T
T
do robienia rzeczyale poza tym dość trudno jest manipulować typami anonimowymi - nie tylko dlatego, że są niezmienne ;-p
Kolejną sztuczką (przy wyodrębnianiu danych) jest również przekazanie selektora - czyli coś takiego:
źródło
Możesz użyć typów ogólnych z następującą sztuczką (rzutowanie na typ anonimowy):
źródło
W tym celu można również użyć terminu „dynamiczny”.
źródło
Zamiast przekazywać anonimowy typ, przekaż Listę typu dynamicznego:
var dynamicResult = anonymousQueryResult.ToList<dynamic>();
DoSomething(List<dynamic> _dynamicResult)
DoSomething(dynamicResult);
Dzięki Petar Ivanov !
źródło
Jeśli wiesz, że twoje wyniki implementują pewien interfejs, możesz użyć interfejsu jako typu danych:
źródło
Użyłbym
IEnumerable<object>
jako typu dla argumentu. Jednak nie jest to wielki zysk dla nieuniknionej wyraźnej obsady. Twoje zdrowieźródło