C# 将IEnumerable数据作为参数从LINQ传递给方法
可能重复: 我有以下LINQ语句,其输出必须用另一种方法处理:C# 将IEnumerable数据作为参数从LINQ传递给方法,c#,linq,C#,Linq,可能重复: 我有以下LINQ语句,其输出必须用另一种方法处理: var data = from lines in File.ReadAllLines(TrainingDataFile) .Skip(ContainsHeader ? 1 : 0) let f = lines.Split(new[] { FieldSeparator }).ToList<String>() let ta
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 };
将获取此数据的方法中参数的数据类型应该是什么?您不能从方法返回匿名数据类型。您可以定义一个类并从查询返回该类的对象,然后将其传递给目标方法
public class SomeClass
{
public string F {get; set;}
public string T {get; set;}
}
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 SomeClass { F=f, T=target };
你不能很容易地传递匿名类型。您可以创建一个类,或者因为数据只有两个属性,所以使用元组: 如果数据类型正确,则参数的数据类型为:
IEnumerable<Tuple<List<string>, string>>
您可以使用元组属性Item1和Item2引用F和T。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..
}
这里需要注意的是,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依赖fiddly反射从匿名类型获取属性,否则
6在方法参数上使用dynamic关键字,现在就有了动态类型。以上两种方法都没有给你静态类型的好处
7你最好有一个单独的班级来容纳F和T,这是最好的。但是问问你自己,它们一起代表了一个实体吗
8如果没有,只需根据重要内容传递IEnumerable或IDictionary
这完全取决于你想用这种方法实现什么/如何实现。就我个人而言,我会在一个爱好项目中选择方法2以获得乐趣,但在生产代码3、4、7、8中,这取决于上下文。您不能从方法返回匿名数据类型。-没错,但问题不是这样问的。问题要求将匿名数据类型传递给方法。当方法是泛型方法时,这是可能的。一个泛型方法在这里是否有用取决于该方法应该做什么。显然,IEnumerable不能接受两个参数…它是一个泛型类1 1参数..所以这不起作用它只有一个参数:Tuple。你试过了吗?那很聪明:……会试的that@Aadith对于类似的例子,考虑标准类型字典,它实现iQueDaby。这是完全正确的:IEnumerable有一个泛型类型参数,即KeyValuePair.or dynamic,也可以使用它。@Yossarian true,但我鄙视它:
IEnumerable<Tuple<List<string>, string>>
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..
}
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(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);
}