Note that there are some explanatory texts on larger screens.

plurals
  1. POC# generics problem - newing up the generic type with parameters in the constructor
    text
    copied!<p>I am trying to create a generic class which new's up an instance of the generic type. As follows:</p> <pre><code>public class HomepageCarousel&lt;T&gt; : List&lt;T&gt; where T: IHomepageCarouselItem, new() { private List&lt;T&gt; GetInitialCarouselData() { List&lt;T&gt; carouselItems = new List&lt;T&gt;(); if (jewellerHomepages != null) { foreach (PageData pageData in jewellerHomepages) { T item = new T(pageData); // this line wont compile carouselItems.Add(item); } } return carouselItems; } } </code></pre> <p>But I get the following error:</p> <blockquote> <p><strong><em>cannot provide arguments when creating an instance of a variable type</em></strong></p> </blockquote> <p>I found the following related question which is very close to what I need: <a href="https://stackoverflow.com/questions/840261/c-generic-new-constructor-problem/1681770#1681770">Passing arguments to C# generic new() of templated type</a></p> <p>However, I can't used Jared's suggested answer as I am calling the method within the Generic class, not outside of it, so I can't specify the concrete class.</p> <p>Is there a way around this?</p> <p>I have tried the following based on the other question, but it doesn't work as I don't know the concrete type of T to specify. As it is called from inside the generic class, not outside:</p> <pre><code>public class HomepageCarousel&lt;T&gt; : List&lt;T&gt; where T: IHomepageCarouselItem, new() { private List&lt;T&gt; 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 =&gt; new T(l)); } private List&lt;T&gt; GetInitialCarouselData(Func&lt;PageData, T&gt; del) { List&lt;T&gt; carouselItems = new List&lt;T&gt;(); if (jewellerHomepages != null) { foreach (PageData pageData in jewellerHomepages) { T item = del(pageData); carouselItems.Add(item); } } return carouselItems; } } </code></pre> <p>********EDIT : ADDED POSSIBLE SOLUTIONS**</p> <p>So I have tested 2 possible solutions:</p> <p>First is exactly as explained below by <a href="https://stackoverflow.com/users/22656/jon-skeet">Jon Skeet</a>. This definitely works but means having an obscure lambda in the constructor. I am not very comfortable with this as it means users need to know the correct lambda that is expected. After all, they could pass a lambda which doesn't new up the type, but does something entirely unexpected</p> <p>Secondly, I went down the Factory method route; I added a Create method to the common interface:</p> <pre><code>IJewellerHomepageCarouselItem Create(PageData pageData); </code></pre> <p>Then provided an implementation in each Concrete class:</p> <pre><code>public IJewellerHomepageCarouselItem Create(PageData pageData) { return new JewellerHomepageCarouselItem(pageData, null); } </code></pre> <p>And used a two step initialisation syntax:</p> <pre><code>T carouselItem = new T(); T homepageMgmtCarouselItem = (T) carouselItem.Create(jewellerPage); </code></pre> <p>Would love to hear some feedback on the merit of each of these approaches.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload