【问题标题】:Invoking a method of the key object of a dictionary using lambda expressions使用 lambda 表达式调用字典键对象的方法
【发布时间】:2012-08-22 22:24:00
【问题描述】:

如果我有类似的东西:

Dictionary<SomeObject, SomeOtherObject> _mydictionary 

SomeObject 有一个方法:SomeMethod()

如何使用 lambda 表达式调用方法 SomeMethod() 而无需将键转换为列表并执行 ForEach。 ToList() 太贵了。或者,lambda 中的等价物:

foreach(SomeObject o in _mydictionary.Keys)
  o.SomeMethod();

???

我试过了:

_mydictionary.ToList().ForEach(x => x.SomeMethod());

但这对于ToList();来说似乎太贵了

【问题讨论】:

  • FWIW,我会坚持使用您的 foreach 循环。它非常清晰简洁。
  • 对于好奇的人来说,这里有一个合理的解释为什么 IEnumerable 没有 ForEach 扩展方法:“foreach” vs “ForEach”
  • ForEach() 在 List 上,而不是 IEnumerable 的扩展方法,所以如果你不编写自己的 ext 方法,是的,你必须使用 ToList()或foreach

标签: c# linq lambda


【解决方案1】:

使用Reactive Extensions (Rx)

var keys = _mydictionary.Keys;
// convert the enumerable sequence of keys to an observable sequence
var observableKeys = keys.ToObservable ();
// invoke SomeMethod for each key
await observableKeys.ForEachAsync (obj =>
    obj.SomeMethod ());

在调用第一个 SomeMethod 之前,此代码将在不阻塞枚举序列的调用的情况下执行,并且不会分配另一个集合。

不幸的是,交互式扩展 (Ix) 的 we're waiting for a new release 具有完全相同的功能,而无需从可枚举序列转换为可观察序列。

【讨论】:

  • IX 不是在 Windows 8 客户端 SDK 几个月后发布的吗? @GeorgeTsiokos:是时候刷新答案了吗?
【解决方案2】:

没有用于调用void 方法集合的内置扩展方法,无论是委托还是对象集合的成员。

但是,您可以相对轻松地创建一个:

public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
{
  foreach (var item in items) action(item);
}

现在您可以以 LINQish 方式调用所有这些方法:

_mydictionary.Keys.ForEach(x => x.SomeMethod());

您已经可以访问IDictionary&lt;TKey,TValue&gt; 上的.Keys 集合属性;您无需在任何地方致电.ToList()


如果SomeMethod()是一个函数,并且你想创建一个结果集,那么你可以使用内置的扩展方法Select()

var results = _mydictionary.Keys.Select(x => x.SomeMethod());

正如 George 正确指出的那样,除非需要,否则不会调用 SomeMethod(),也就是说,除非您通过迭代它们来实际使用结果。这可以避免创建新集合的开销,但应注意避免多次枚举。

【讨论】:

  • 这导致了几乎相同的问题。 Select 需要一个返回值(如果 SomeMethod 为 void,您的代码将无法编译)在这种情况下它会创建 另一个集合...
  • @jay 是的,我确实读到了你的回答,因此关于创建另一个集合的评论。您在我的评论之后添加了关于void 的注释。 OP 没有提及创建函数返回的类型的另一个集合(其存在似乎似是而非)。如果 OP 担心 正在使用ToList(),那么 OP 会担心另一个集合 没有被使用——尤其是如果它是nulls.
  • @user1615606 你可以使用我在答案中给出的扩展方法,跳过ToList()
  • @PeterRitchie 请阅读整个答案。重点是您使用ForEach 扩展方法来调用void 方法。这最初是并且仍然是我回答的核心。没有编译器错误。扩展方法实现在答案中;自己试试吧。
  • Select() 不会做任何事情,除非你枚举你的“忽略”可枚举序列
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 2021-12-10
  • 1970-01-01
  • 2016-02-25
相关资源
最近更新 更多