Próbuję utworzyć klasę ogólną, która jest nową instancją typu ogólnego. W następujący sposób:C# problem generyczny - tworzenie nowego typu ogólnego z parametrami w konstruktorze
public class HomepageCarousel<T> : List<T>
where T: IHomepageCarouselItem, new()
{
private List<T> GetInitialCarouselData()
{
List<T> carouselItems = new List<T>();
if (jewellerHomepages != null)
{
foreach (PageData pageData in jewellerHomepages)
{
T item = new T(pageData); // this line wont compile
carouselItems.Add(item);
}
}
return carouselItems;
}
}
Ale pojawia się następujący błąd:
cannot provide arguments when creating an instance of a variable type
znalazłem następujące powiązane pytanie, który jest bardzo zbliżony do tego, co potrzebne: Passing arguments to C# generic new() of templated type
Jednak mogę” t użyłem sugerowanej odpowiedzi Jareda, ponieważ jestem nazywając metodę wewnątrz klasy Generic, a nie poza , więc nie mogę określić konkretnej klasy.
Czy istnieje sposób obejścia tego?
Próbowałem na podstawie innego pytania, ale to nie działa, ponieważ nie wiem konkretny typ T do określić. Jak nazywa się od wewnątrz klasy rodzajowej, nie zewnątrz:
public class HomepageCarousel<T> : List<T>
where T: IHomepageCarouselItem, new()
{
private List<T> LoadCarouselItems()
{
if (IsCarouselConfigued)
{
return GetConfiguredCarouselData();
}
// ****** I don't know the concrete class for the following line,
// so how can it be instansiated correctly?
return GetInitialCarouselData(l => new T(l));
}
private List<T> GetInitialCarouselData(Func<PageData, T> del)
{
List<T> carouselItems = new List<T>();
if (jewellerHomepages != null)
{
foreach (PageData pageData in jewellerHomepages)
{
T item = del(pageData);
carouselItems.Add(item);
}
}
return carouselItems;
}
}
******** EDIT: Dodano możliwych rozwiązań **
Więc ja testowałem 2 możliwe rozwiązania:
Pierwsza jest dokładnie taka, jak wyjaśniono poniżej przez Jon Skeet. Ten zdecydowanie działa, ale oznacza posiadanie niejasnego lambda w konstruktorze . Nie jestem z tym bardzo zadowolony, ponieważ oznacza to, że użytkownicy muszą znać poprawną lambdę, która jest oczekiwana. Przecież mogliby przekazać lambdę, która nie jest nowsza niż typ , ale robi coś zupełnie nieoczekiwanego
Po drugie, przeszedłem ścieżką metody Factory; dodałem Tworzenie metodę wspólnego interfejsu:
IJewellerHomepageCarouselItem Create(PageData pageData);
Następnie pod warunkiem wdrożenia w każdej klasie betonu:
public IJewellerHomepageCarouselItem Create(PageData pageData)
{
return new JewellerHomepageCarouselItem(pageData, null);
}
i używane dwuetapowego inicjalizacji składni:
T carouselItem = new T();
T homepageMgmtCarouselItem = (T) carouselItem.Create(jewellerPage);
Would Uwielbiam słyszeć pewne opinie na temat zalet każdego z tych podejść.
możliwy duplikat [przekazywanie argumentów do C# generic new() typu szablonowego] (http://stackoverflow.com/questions/840261/passing -argumenty-do-c-ostry-generic-new-of-templated-type) – nawfal