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此处显示的“示例转换”技巧。引用他的话:
我们使用方法类型推断和局部变量类型推断来告诉编译器“这两个东西是同一类型”。这使您可以将匿名类型导出为对象并将其转换回匿名类型。
...该技巧仅在示例和源对象是在同一程序集中的代码中创建时才有效;两个不同程序集中的两个“相同”匿名类型不会统一为同一类型。
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
通过多一个类型参数来委托。
5)否则,请依靠精巧的反射从您的匿名类型中获取属性。
6)dynamic
在方法参数上使用关键字,现在你有了动态类型。以上都没有给你静态类型的好处。
7) 你最好有一个单独的类来保存F
和T
。这是最好的。但是问问你自己,它们是否一起代表了一个实体?
8)如果没有,只需通过IEnumerable<Tuple>
或IDictionary
取决于重要的事情。
这完全取决于您希望使用该方法实现什么/如何实现。就个人而言,我会在一个爱好项目中选择方法 2(为了获得乐趣),但在生产代码 3、4、7、8 中取决于上下文。