C#泛型的问题 - newing了泛型类型的构造函数的参数 [英] C# generics problem - newing up the generic type with parameters in the constructor

查看:192
本文介绍了C#泛型的问题 - newing了泛型类型的构造函数的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个通用类新的了泛型类型的实例。具体如下:

I am trying to create a generic class which new's up an instance of the generic type. As follows:

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;
    }
}

不过,我得到以下错误:

But I get the following error:

不能创建变量的实例时提供的参数
  键入

cannot provide arguments when creating an instance of a variable type

我发现了以下相关的问题,这是非常接近我所需要的:
<一href=\"http://stackoverflow.com/questions/840261/c-generic-new-constructor-problem/1681770#1681770\">http://stackoverflow.com/questions/840261/c-generic-new-constructor-problem/1681770#1681770

I found the following related question which is very close to what I need: http://stackoverflow.com/questions/840261/c-generic-new-constructor-problem/1681770#1681770

不过,我不能用Jared的建议答案我
调用泛型类中的方法,而不是外界的
,所以我不能指定具体类。

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.

有没有办法解决?

我曾尝试根据其他问题的下面,但
这是行不通的,因为我不知道具体的类型T的
指定。由于它是从通用类里面,不叫
外:

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:

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 : ADDED POSSIBLE SOLUTIONS**

所以,我已经测试了2可能的解决方案:

So I have tested 2 possible solutions:

首先是完全按照低于乔恩斯基特解释。这个
绝对有效,但指具有在一个不起眼的lambda
构造函数。我不是很舒服的这个,因为它意味着
用户需要知道预期正确的lambda。
毕竟,他们能够通过一个lambda这不新了
类型,但做了完全出乎意料的。

First is exactly as explained below by Jon Skeet. 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

其次,我去了工厂方法途径;
我添加了一个到通用接口创建方式:

Secondly, I went down the Factory method route; I added a Create method to the common interface:

IJewellerHomepageCarouselItem Create(PageData pageData);

然后在每个具体的类提供了一个实现:

Then provided an implementation in each Concrete class:

public IJewellerHomepageCarouselItem Create(PageData pageData)
{
     return new JewellerHomepageCarouselItem(pageData, null);
}

和使用两个步骤的初始化语法:

And used a two step initialisation syntax:

T carouselItem = new T();
T homepageMgmtCarouselItem = (T) carouselItem.Create(jewellerPage);

很想听听你对每种方法的优点的一些反馈。

Would love to hear some feedback on the merit of each of these approaches.

推荐答案

Jared的回答仍然是一个很好的路要走 - 你只需要做出的构造采取 Func键&LT; PageData,T&GT; 并藏匿起来以备以后:

Jared's answer is still a good way to go - you just need to make the constructor take the Func<PageData, T> and stash it for later:

public class HomepageCarousel<T> : List<T> where T: IHomepageCarouselItem
{
    private readonly Func<PageData, T> factory;

    public HomepageCarousel(Func<PageData, T> factory)
    {
        this.factory = factory;
    }

    private List<T> GetInitialCarouselData()
    {
       List<T> carouselItems = new List<T>();

       if (jewellerHomepages != null)
       {
            foreach (PageData pageData in jewellerHomepages)
            {
                T homepageMgmtCarouselItem = factory(pageData);
                carouselItems.Add(homepageMgmtCarouselItem);
            }
       }
       return carouselItems;
    }

然后你只传递给函数到您创建的新实例构造函数中的 HomepageCar​​ousel&LT; T&GT;

(我建议组成,而不是继承,顺便说一句......从导出列表&LT; T&GT; 几乎总是错的路要走。)

(I'd recommend composition instead of inheritance, btw... deriving from List<T> is almost always the wrong way to go.)

这篇关于C#泛型的问题 - newing了泛型类型的构造函数的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆