0

多くのクラスが継承するSCOという基本クラスがあります。最初はコレクションを並べ替えたかったのですが、いくつかの推奨事項に基づいて、1つの方法でコレクションをインスタンス化して並べ替えることができるようです。

私はすべての基本クラスが継承するこのコンストラクターを持っています:

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"]));
}

これは私が立ち往生しているところです。インスタンス化できません<T>

public static List<T> SortedCollection<T>(SPListItemCollection items, ListSortType sortType, List<Vote> votes) where T : SCO
{
    var returnlist = new List<T>();
    for (int i = 0; i < items.Count; i++) { returnlist.Add(new T(items[i], votes)); }
    switch (sortType)
    {
        // Sort List based on passed ENUM
    }
    return returnlist;
}

これらすべてを1つの方法で実行できれば、コストのかかるキャスティングとボクシングを回避できます。

4

3 に答える 3

3

ジェネリックスで許容される唯一の制約はですnew()。これは、パラメーターを受け取らないコンストラクターがある場合にのみ機能します。

私はすべての基本クラスが継承するこのコンストラクターを持っています:

問題は、これが強制できないことです。サブクラスは、このコンストラクターにチェーンされている限り、独自のコンストラクターを自由に定義できます(また、そうする必要があります)。サブクラスは、そのクラスをインスタンス化するために必要な構築メカニズムを自由に使用できます。

リフレクションとActivator.CreateInstanceを使用してこれを回避できます。これにより、パラメーターを使用してオブジェクトを作成できます。ただし、これはかなり「醜い」です(ただし、new()制約を使用してもActivator.CreateInstanceが呼び出されることを考えると、それほど醜いわけはありません)。

Type genericType = typeof(T);
for (int i = 0; i < items.Count; i++) 
{ 
     returnlist.Add((T)Activator.CreateInstance(genericType, new object[] {items[i], votes})); 
}
于 2012-08-24T23:49:20.590 に答える
2

ここで欠落しているのは、Tオブジェクトをインスタンス化するための手段よりも一般的なものです。

new T(items[i], votes)

コンパイラーは、このコンストラクターがすべての型に存在することを保証できませんT。あなたができることは、関数に追加のパラメータとしてタイプのファクトリメソッドを受け入れさせることですFunc<SPListItem, IList<Vote>, T>。これにより、上記を書き直すことができます。

returnlist.Add(factory(items[i], votes))

または、代わりに、コード内のタイプごとにこのインスタンス化ロジックを効果的に含むファクトリクラスを実装することもできますSCO

class SCOFactory
{
    public T Create<T>(SPListItem item, IList<Vote> votes) where T : SCO
    {
        // Do your instantiation here.
    }
}

これはよく見られます(「ファクトリパターン」と呼ばれることもあります)。メソッドとしては少し醜い場合がありますが(多くの場合、巨大なswitchステートメント)、少なくとも1つの場所に醜さが含まれており、別のパラメーターを追加して最終的に混乱させることなく、質問のような関数を記述できます。プロジェクト内の多くのコード。

一般的な注意事項(もちろん、一粒の塩でとらえるべきです):コードを過度に一般化すると、具体的なメリットが得られずに、最終的には頭痛の種になる可能性があります。先に進む前に、このような一般的な方法でこのコードを書くことが本当に有益かどうかを自問してください。もしそうなら、上記の提案のいずれかがまともな出発点を証明するかもしれません。そうでない場合は、理論的には柔軟性が低いかもしれませんが、実際には扱いやすい、より単純なアプローチを採用することを検討してください。

于 2012-08-24T23:52:30.010 に答える
0

それらの値をコンストラクターに渡す必要がありますか?

型にこれらの設定可能なプロパティを作成し、デフォルトのコンストラクターを呼び出すことができます。オブジェクトが作成された後、プロパティを設定するだけです...

于 2012-08-25T00:03:43.410 に答える