Jak zdefiniować metodę rozszerzenia dla IEnumerable<T>
, która zwraca IEnumerable<T>
? Celem jest udostępnienie metody rozszerzenia dla wszystkich IEnumerable
i IEnumerable<T>
, gdzie T
może być anonimowy.Zdefiniuj metodę rozszerzenia dla IEnumerable <T>, która zwraca IEnumerable <T>?
Odpowiedz
Najłatwiej napisać dowolny iterator jest z bloku iteracyjnej, na przykład:
static IEnumerable<T> Where<T>(this IEnumerable<T> data, Func<T, bool> predicate)
{
foreach(T value in data)
{
if(predicate(value)) yield return value;
}
}
Kluczem tutaj jest „yield return
”, który zamienia metody w bloku iteracyjnej, ze kompilator generując moduł wyliczający (IEnumerator<T>
), który robi to samo. Po wywołaniu, ogólne typ wnioskowanie obsługuje T
automatycznie, więc wystarczy:
int[] data = {1,2,3,4,5};
var odd = data.Where(i=>i%2 != 0);
Powyższe może być używany z anonimowych typów dobrze.
Można, Coure określ T
jeśli chcesz (tak długo, jak nie jest anonimowy):
var odd = data.Where<int>(i=>i%2 != 0);
Re IEnumerable
(non-generic), dobrze, najprostszym rozwiązaniem jest dla program wywołujący, aby najpierw użyć .Cast<T>(...)
lub .OfType<T>(...)
, aby uzyskać IEnumerable<T>
. Możesz przekazać w powyższym numerze this IEnumerable
, ale osoba wywołująca będzie musiała sama określić wartość T
, zamiast wnioskować o tym kompilator. Nie można tego używać z T
jako typ anonimowy, więc morał tutaj jest następujący: nie używaj nietypowej formy IEnumerable
z typami anonimowymi.
Istnieje kilka bardziej złożonych scenariuszy, w których sygnatura metody jest taka, że kompilator nie może zidentyfikować T
(i oczywiście nie można jej określić dla typów anonimowych). W takich przypadkach zwykle możliwe jest ponowne uwzględnienie w innym sygnaturze, którą kompilator może zastosować z wnioskiem (być może za pomocą metody pass-thru), ale trzeba podać aktualny kod, aby podać tutaj odpowiedź.
(aktualizacja)
Po dyskusji, oto sposób na wykorzystanie Cast<T>
z anonimowych typów. Kluczem jest podanie argumentu, który może być użyty do wnioskowania o typ (nawet jeśli argument nie jest nigdy używany). Na przykład:
static void Main()
{
IEnumerable data = new[] { new { Foo = "abc" }, new { Foo = "def" }, new { Foo = "ghi" } };
var typed = data.Cast(() => new { Foo = "never used" });
foreach (var item in typed)
{
Console.WriteLine(item.Foo);
}
}
// note that the template is not used, and we never need to pass one in...
public static IEnumerable<T> Cast<T>(this IEnumerable source, Func<T> template)
{
return Enumerable.Cast<T>(source);
}
Ten wpis może pomóc rozpocząć: How do you write a C# Extension Method for a Generically Typed Class. Nie jestem pewien, czy to dokładnie to, czego szukasz, ale może zacząć.
using System;
using System.Collections.Generic;
namespace ExtentionTest {
class Program {
static void Main(string[] args) {
List<int> BigList = new List<int>() { 1,2,3,4,5,11,12,13,14,15};
IEnumerable<int> Smalllist = BigList.MyMethod();
foreach (int v in Smalllist) {
Console.WriteLine(v);
}
}
}
static class EnumExtentions {
public static IEnumerable<T> MyMethod<T>(this IEnumerable<T> Container) {
int Count = 1;
foreach (T Element in Container) {
if ((Count++ % 2) == 0)
yield return Element;
}
}
}
}
To jest buforowany iterator; zazwyczaj lepiej byłoby zamiast tego używać bloku iteratora - np. upuszczać listę "List
(dla kontekstu, pierwotna wersja miała listę
- 1. IEnumerable <IEnumerable <T>> do IEnumerable <T> użyciu LINQ
- 2. Spłaszczyć IEnumerable <IEnumerable <>>; zrozumienia rodzajowych
- 3. IEnumerable <> to IList <>
- 4. Dlaczego funkcja, która trwa IEnumerable <interface>, nie przyjmuje IEnumerable <class>?
- 5. Dlaczego IEnumerable <T> jest zdefiniowany jako IEnumerable <out T>, nie IEnumerable <T>
- 6. Konwertuj na IEnumerable <dynamic>?
- 7. Przesyłanie z IEnumerable <Object> do IEnumerable <string>
- 8. Jak napisać ogólną IEnumerable <SelectListItem> metoda rozszerzenia
- 9. Różnica między IEnumerable i IEnumerable <T>?
- 10. Jak połączyć dwa IEnumerable <T> w nowy IEnumerable <T>?
- 11. Przesyłaj/przeliczaj IEnumerable <T> na IEnumerable <U>?
- 12. C# Nie można przekonwertować z IEnumerable <Base> do IEnumerable <Derived>
- 13. IEnumerable <T> i IQueryable <T> wyjaśnienie?
- 14. Jak sprawdzić, czy `IEnumerable <T1>` covariant do `IEnumerable <T2>`?
- 15. F # odpowiednik C# typeof (IEnumerable <>)
- 16. Konwersja tablicy do IEnumerable <T>
- 17. XML do IEnumerable <T>
- 18. Konwertuj DataTable na IEnumerable <T>
- 19. dołączyć kilka IEnumerable <> użyciu LINQ
- 20. IEnumerable <T> w OCaml
- 21. Konwertuj IEnumerable <int> na int []
- 22. Problemy implementujące IEnumerable <T>
- 23. Jak zrobić IEnumerable <T> readonly?
- 24. export IEnumerable <T> do Excela
- 25. NET Reflection: Wykrywanie IEnumerable <T>
- 26. Licz na IEnumerable <dynamic>
- 27. Jak działa IEnumerable <T>.
- 28. IEnumerable <T> vs IReadOnlyList <T>
- 29. Lista <int> do IEnumerable <IComparable>
- 30. Casting IEnumerable <T> do listy <T>
metodę z parametrem, który nie jest używany tylko wydaje się błędne. –
It * is * used .... tylko przez kompilator, a nie przez środowisko wykonawcze; - –
Jest używany i dostarczany, ale nie jawny, a raczej jest wywiedziony ... Bez kompilatora C# jest "tak inteligentny" być zmuszonym do wyraźnego określenia go. –