C# 创建一个<;T>;来自基类

C# 创建一个<;T>;来自基类,c#,generics,inheritance,instantiation,C#,Generics,Inheritance,Instantiation,我有一个名为SCO的基类,许多类都是从它继承的。起初我只是想对集合进行排序,但根据一些建议,听起来我可以用一个方法实例化集合并对其进行排序 我有一个所有基类都继承的构造函数: public SCO(SPListItem item, List<Vote> votes) { UpVotes = voteMeta.UpVotes; DownVotes = voteMeta.DownVotes; VoteTotal = UpVotes - DownVotes;

我有一个名为SCO的基类,许多类都是从它继承的。起初我只是想对集合进行排序,但根据一些建议,听起来我可以用一个方法实例化集合并对其进行排序

我有一个所有基类都继承的构造函数:

public SCO(SPListItem item, List<Vote> votes)
{
    UpVotes = voteMeta.UpVotes;
    DownVotes = voteMeta.DownVotes;
    VoteTotal = UpVotes - DownVotes;
    HotScore = Calculation.HotScore(Convert.ToInt32(UpVotes), Convert.ToInt32(DownVotes), Convert.ToDateTime(item["Created"]));
}
public SCO(列表项,列表投票)
{
UpVoces=voteMeta.UpVoces;
下行票=voteMeta.下行票;
VoteTotal=上升票-下降票;
HotScore=计算.HotScore(Convert.ToInt32(向上投票)、Convert.ToInt32(向下投票)、Convert.ToDateTime(项目[“已创建]);
}
这就是我被卡住的地方。我无法实例化

publicstaticlist-SortedCollection(SPListItemCollection项目,ListSortType,列表投票),其中T:SCO
{
var returnlist=新列表();
对于(inti=0;i

如果我可以在一个方法中完成所有这些,我就可以避免一些昂贵的强制转换和装箱。

泛型中唯一允许的约束是
new()
,只有当存在不接受任何参数的构造函数时,它才会起作用

我有一个所有基类都继承的构造函数:

public SCO(SPListItem item, List<Vote> votes)
{
    UpVotes = voteMeta.UpVotes;
    DownVotes = voteMeta.DownVotes;
    VoteTotal = UpVotes - DownVotes;
    HotScore = Calculation.HotScore(Convert.ToInt32(UpVotes), Convert.ToInt32(DownVotes), Convert.ToDateTime(item["Created"]));
}
问题是这是不可执行的。子类可以(并且应该)自由定义自己的构造函数,只要它们链接到此构造函数。子类可以自由使用实例化该类所需的任何构造机制

您可以通过反射和反射来解决这个问题,这将允许您使用参数构造对象。然而,这是相当“丑陋的”(尽管,考虑到使用

Type genericType=typeof(T);
对于(int i=0;i
泛型中唯一允许的约束是
new()
,只有当存在不接受任何参数的构造函数时,该约束才会起作用

我有一个所有基类都继承的构造函数:

public SCO(SPListItem item, List<Vote> votes)
{
    UpVotes = voteMeta.UpVotes;
    DownVotes = voteMeta.DownVotes;
    VoteTotal = UpVotes - DownVotes;
    HotScore = Calculation.HotScore(Convert.ToInt32(UpVotes), Convert.ToInt32(DownVotes), Convert.ToDateTime(item["Created"]));
}
问题是这是不可执行的。子类可以(并且应该)自由定义自己的构造函数,只要它们链接到此构造函数。子类可以自由使用实例化该类所需的任何构造机制

您可以通过反射和反射来解决这个问题,这将允许您使用参数构造对象。然而,这是相当“丑陋的”(尽管,考虑到使用

Type genericType=typeof(T);
对于(int i=0;i
这里缺少的是比实例化
T
对象的方法更通用的东西:

new T(items[i], votes)
编译器无法保证每个类型
t
都存在此构造函数。您所能做的是让函数接受某种类型为
Func
的工厂方法作为附加参数,以便重写上述内容:

returnlist.Add(factory(items[i], votes))
或者,您也可以实现一个factory类,该类有效地包含源于
SCO
的代码中每种类型的实例化逻辑,例如:

class SCOFactory
{
    public T Create<T>(SPListItem item, IList<Vote> votes) where T : SCO
    {
        // Do your instantiation here.
    }
}
class工厂
{
公共T创建(SPListItem,IList投票),其中T:SCO
{
//在这里进行实例化。
}
}
你经常会看到这种情况(通常被称为“工厂模式”);作为一种方法,它可能有点难看(通常是一个巨大的
开关
语句),但至少它在一个地方包含了难看的地方,并且允许您编写函数,比如您问题中的函数,而无需添加另一个参数,最终会使项目中的大量代码变得混乱


有一句话要提醒大家(当然要谨慎):过度泛化代码最终可能会导致头痛,而不会产生太多实际的好处。在继续之前问问自己,以这样一种通用的方式编写此代码是否真的对您有益;如果是这样,以上任何一个建议都可能是一个不错的起点。如果不是,考虑一个更简单的方法,它可能在理论上不太灵活,但在实践中更容易处理。

这里缺少的是比实例化<代码> t>代码>对象的方法更通用的:

new T(items[i], votes)
编译器无法保证每个类型
t
都存在此构造函数。您所能做的是让函数接受某种类型为
Func
的工厂方法作为附加参数,以便重写上述内容:

returnlist.Add(factory(items[i], votes))
或者,您也可以实现一个factory类,该类有效地包含源于
SCO
的代码中每种类型的实例化逻辑,例如:

class SCOFactory
{
    public T Create<T>(SPListItem item, IList<Vote> votes) where T : SCO
    {
        // Do your instantiation here.
    }
}
class工厂
{
公共T创建(SPListItem,IList投票),其中T:SCO
{
//在这里进行实例化。
}
}
你经常会看到这种情况(通常被称为“工厂模式”);作为一种方法,它可能有点难看(通常是一个巨大的
开关
语句),但至少它在一个地方包含了难看的地方,并且允许您编写函数,比如您问题中的函数,而无需添加另一个参数,最终会使项目中的大量代码变得混乱

有一句话要提醒大家(当然要谨慎):过度泛化代码最终可能会导致头痛,而不会产生太多实际的好处。在继续之前问问自己,以这样一种通用的方式编写此代码是否真的对您有益;如果是这样,以上任何一个建议都可能是一个不错的起点。如果不是,考虑一个更简单的方法,在理论上可能不那么灵活,但在实践中更容易操作。