1) クエリの結果を渡すためだけに、関数をジェネリックにします。
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new { F=f, T=target };
SomeMethod(data);
public void SomeMethod<T>(IEnumerable<T> enumerable)
{
// ^^choose the return type..
}
単純。メソッド内の処理が非常に単純なものであれば、これで十分です。F
ただし、プロパティやT
メソッド内にはアクセスできません。
そうするために:
2)ここで Eric が示した「例によるキャスト」トリックを使用できます。彼を引用するには:
メソッドの型推論とローカル変数の型推論を使用して、「これら 2 つのものが同じ型である」ことをコンパイラに伝えます。これにより、匿名型をオブジェクトとしてエクスポートし、匿名型にキャストできます。
...このトリックは、例とソース オブジェクトが同じアセンブリ内のコードで作成された場合にのみ機能します。2 つの異なるアセンブリ内の 2 つの "同一の" 匿名型は、同じ型に統一されません。
SomeMethod(data);
public void SomeMethod(IEnumerable<object> enumerable)
{
var template = new { F = new List<string>(), T = string.Empty };
foreach (var item in enumerable)
{
var anonymousType = item.CastToTypeOf(template);
//print string.Join(", ", anonymousType.F) + " - " + anonymousType.T //compiles
//or whatever
}
}
//a more generic name perhaps is 'CastToTypeOf' as an extension method
public static T CastToTypeOf<T>(this object source, T example) where T : class
{
return (T)source;
}
ここでの問題はSomeMethod
、メソッド内で特定の型を指定しているため、匿名型に合わせて作成されているため、関数をジェネリックにしないで (可能ですが)、関数に適切な名前を付けることをお勧めします。 .
3)関数が今あなたのユニークなタイプだけのものである場合、それらをすべて単一のメソッドにラップし、まったく渡さないようにすることをお勧めします-面倒なことはありません!:)
4) または、匿名型で実行されるアクションを委任できます。したがって、メソッドの署名は次のようになります。
SomeMethod(data, d => print string.Join(", ", d.F) + " - " + d.T);
public void SomeMethod<T>(IEnumerable<T> enumerable, Action<T> actor)
{
foreach (var item in enumerable)
actor(item);
}
重要な場合はFunc
、型引数をもう 1 つ持つことでデリゲートも使用できます。
5) それ以外の場合は、匿名型からプロパティを取得するために手間のかかるリフレクションに依存します。
6)dynamic
メソッドの引数にキーワードを使用すると、動的型付けができます。上記の両方は、静的型付けの利点を提供しません。
F
7)とを保持する別のクラスを用意したほうがよいでしょうT
。そして、それは何よりも最高です。しかし、それらが一緒になってエンティティとして何かを表しているか自問してみてください。
8) そうでない場合は、問題に応じてIEnumerable<Tuple>
orを渡します。IDictionary
それはすべて、メソッドで何を/どのように達成したいかによって異なります。個人的には、趣味のプロジェクトでは (楽しみのために) アプローチ 2 を使用しますが、実稼働コードではコンテキストに応じて 3、4、7、8 を使用します。