这是一个带foreach
循环的简单方法:
IEnumerable<XElement> FieldsToXElements(object instance)
{
var fieldElements = new List<XElement>();
foreach (var field in instance.GetType().GetFields(instance))
{
fieldElements.Add(new XElement(field.Name, field.GetValue(instance)));
}
return fieldElements;
}
有点难看。如果LINQ中有一些运算符意味着“做某事”(例如对LINQ语句中选择的每一个执行Action
),那么它看起来会更好,更简洁:
IEnumerable<XElement> FieldsToXElements(object instance)
{
var fieldElements = new List<XElement>();
from field in instance.GetType().GetFields(instance))
let name = field.Name
let value = field.GetValue(instance)
do fieldElements.Add(new XElement(name, value));
return fieldElements;
}
我意识到这是主观的,只是我的意见。对于一个只有一行调用方法的foreach循环,我认为“do
”运算符是有意义的。 但我想知道MS的任何人是否也想过同样的事情。这样的LINQ运营商是否计划在任何即将发布的版本中(例如,与C#4.0首次亮相)?
这是另一个带谓词的例子,其中虚构的do
运算符会使代码看起来更干净。这样:
IEnumerable<XElement> FieldsToXElements
(object instance, Func<FieldInfo, bool> predicate)
{
var fieldElements = new List<XElement>();
foreach (var field in instance.GetType().GetFields(instance).Where(predicate))
{
fieldElements.Add(new XElement(field.Name, field.GetValue(instance)));
}
return fieldElements;
}
VS。这样:
IEnumerable<XElement> FieldsToXElements
(object instance, Func<FieldInfo, bool> predicate)
{
var fieldElements = new List<XElement>();
from field in instance.GetType().GetFields(instance))
let name = field.Name
let value = field.GetValue(instance)
where predicate(field)
do fieldElements.Add(new XElement(name, value));
return fieldElements;
}
答案 0 :(得分:16)
不,我不希望任何直接的语言支持(即在查询语法中)。
听起来你的意思是神话般的ForEach
扩展方法;添加很简单,但Eric Lippert多次评论了无副作用的功能代码和Action<T>
之间的交叉副作用。特别是,C#3.0 / .NET 3.5表达式树在side-effecs上很糟糕(使得完整的lambda支持变得棘手)。运行时端is much better in .NET 4.0,但目前尚不清楚这将使它成为C#4.0语言(lambda编译器)中的多少。
您需要的(代表版本)是:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{ // note: omitted arg/null checks
foreach(T item in source) { action(item); }
}
然后,您可以从任何查询中使用.ForEach(x => /* do something */)
。
答案 1 :(得分:3)
对于您的具体示例(填充List<XElement>
),我会这样做。
IEnumerable<XElement> FieldsToXElements(object instance)
{
List<XElement> fieldElements =
(
from field in instance.GetType().GetFields(instance))
let name = field.Name
let value = field.GetValue(instance)
select new XElement(name, value)
).ToList(); //Another Option is List<T>.AddRange()
return fieldElements;
}
另外:不要忘记List<T>
已经实现.ForEach<T>()
,因此要对任何Enumerable<T>
使用它,这就是您需要的所有代码。
myEnumerable.ToList().ForEach( x => myAction(x) );
答案 2 :(得分:2)
我不认为这太难了或者我错过了什么......
IEnumerable<XElement> FieldsToXElements(object instance)
{
return instance.GetType()
.GetFields(instance)
.Select( f => new XElement( f.Name,
f.GetValue(instance) ) );
}
答案 3 :(得分:1)
如果您只是想在linq语句中调用函数,那么您已经可以这样做了,您可以在Let赋值中调用函数。
var qry = from e in somelist
let errorcode = DoSomeProcessing(e)
select e;