6

私は自分のクラスで以下の関数を使い続けており、それをジェネリックとして書きたいと思っています。

public static IEnumerable<MyObject> Get(string csvFile)
{
    return csvFile
        .ReadAsStream()
        .SplitCrLf()
        .Where(row => !string.IsNullOrWhiteSpace(row))
        .Select(row => new MyObject(row.Split(',')));
}

以下のコードをスクラッチしましたが、機能しませんでした

public static IEnumerable<T> Get<T>(string csvFile)
{
    return csvFile
        .ReadAsStream()
        .SplitCrLf()
        .Where(row => !string.IsNullOrWhiteSpace(row))
        .Select(row => new typeof(T)(row.Split(',')));
}

お知らせ下さい。ありがとうございました!

4

1 に答える 1

11

newこの方法でジェネリック型を使用してインスタンスを作成するために使用することはできません1。関数にファクトリデリゲートを提供することを検討してください。

public static IEnumerable<T> Get<T>(string csvFile, Func<string[], T> factory)
{
    return csvFile
        .ReadAsStream()
        .SplitCrLf()
        .Where(row => !string.IsNullOrWhiteSpace(row))
        .Select(row => factory(row.Split(',')));
}

次に、あなたはそれをそのように呼ぶでしょう:

var myObjects = Get("file.csv", row => new MyObject(row));

IEnumerable<string[]>または、 2を返し、発信者にそれをどうするかを決定させることもできます。

public static IEnumerable<string[]> Get(string csvFile)
{
    return csvFile
        .ReadAsStream()
        .SplitCrLf()
        .Where(row => !string.IsNullOrWhiteSpace(row))
        .Select(row => row.Split(','));
}

次に、発信者は次のことができます。

var myObjects = Get("file.csv").Select(row => new MyObject(row));

1where T : new()制約を指定してから、ジェネリック型を使用して新しいインスタンスを作成できますが、引数のないコンストラクターが提供されている場合に限ります。ジェネリック型を作成するときに引数を指定することはできず、ユースケースで引数を指定する必要があるようです。ここでは、ファクトリデリゲートが最善の選択肢です。

参考までに、これは、ジェネリック型を使用した構築が引数なしの場合にどのように見えるかを示しています。

public static T Create<T>() where T : new()
{
    return new T();
}

2コンストラクターも受け入れるとIEnumerable<IEnumerable<string>>仮定すると、さらに良いでしょう。MyObjectIEnumerable<string>

于 2013-01-22T16:00:25.210 に答える