C# foreach 接口集合

发布于 2024-12-07 19:38:26 字数 613 浏览 1 评论 0原文

我想知道 C#/LINQ 中是否内置了任何功能来简化以下内容:

foreach(var item in collection)
{
    if (item.GetType() == typeof(Type1)
         DoType1(item as Type1);
    else if (item.GetType() == typeof(Type2))
         DoType2(item as Type2);
    ...
}

类似于:

collection.ForEachType(Type1 item => DoType1(item), Type2 item => DoType2(item));

我意识到以下内容很接近:

collection.OfType<Type1>.ToList().Foreach(item => DoType1(item));
collection.OfType<Type2>.ToList().Foreach(item => DoType2(item));

但当代码依赖于以下顺序时它不起作用收藏。

I'm wondering if there is any functionality built in to C#/LINQ to simplify the following:

foreach(var item in collection)
{
    if (item.GetType() == typeof(Type1)
         DoType1(item as Type1);
    else if (item.GetType() == typeof(Type2))
         DoType2(item as Type2);
    ...
}

to something along the lines of:

collection.ForEachType(Type1 item => DoType1(item), Type2 item => DoType2(item));

I realize that the following is close:

collection.OfType<Type1>.ToList().Foreach(item => DoType1(item));
collection.OfType<Type2>.ToList().Foreach(item => DoType2(item));

But it does not work when the code is dependent on the order of the collection.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

戏舞 2024-12-14 19:38:27

我首先要考虑的是多态性;我可以使用虚拟方法和 item.DoSomething() 吗?

接下来我要考虑的是枚举鉴别器,即

switch(item.ItemType) {
    case ItemType.Foo: ...
    case ItemType.Bar: ...
}

(并将鉴别器添加到公共接口/基类)

如果类型可以是任何东西,那么 4.0 有一个技巧;如果您为每个重载调用相同的方法,您可以使用 dynamic 来担心选择它:

dynamic x = item;
DoSomething(x);

The first thing I'd look at is polymorphism; can I instead use a virtual method, and item.DoSomething()?

The next thing I'd look at would be an enum discriminator, i.e.

switch(item.ItemType) {
    case ItemType.Foo: ...
    case ItemType.Bar: ...
}

(and add the discriminator to the common interface/base-class)

If the types could be anything, then 4.0 has a trick; if you call te method the same thing for every overload, you can get dynamic to worry about picking it:

dynamic x = item;
DoSomething(x);
秋日私语 2024-12-14 19:38:27

LINQ 中没有内置任何内容,不是。我会警告您不要像这样使用 GetType() - 通常使用 isas 后跟 null 检查更合适

foreach(var item in collection)
{
    Type1 itemType1 = item as Type1;
    if (itemType1 != null)
    {
         DoType1(itemType1);
         continue;
    }
    Type2 itemType2 = item as Type1;
    if (itemType2 != null)
    {
         DoType2(itemType1);
         continue;
    }
    // etc
}

:派生类将以通常适当的方式进行处理。

请注意,这种类型测试通常是不受欢迎的 - 通常最好将行为作为虚拟方法放入类型本身,并以多态方式调用它。

There's nothing built into LINQ, no. I would caution you against using GetType() like this though - usually it's more appropriate to use is or as followed by a null check:

foreach(var item in collection)
{
    Type1 itemType1 = item as Type1;
    if (itemType1 != null)
    {
         DoType1(itemType1);
         continue;
    }
    Type2 itemType2 = item as Type1;
    if (itemType2 != null)
    {
         DoType2(itemType1);
         continue;
    }
    // etc
}

That way derived classes will be treated in a way which is usually the appropriate one.

This sort of type testing is generally frowned upon, mind you - it's generally better to put the behaviour into the type itself as a virtual method, and call it polymorphically.

彡翼 2024-12-14 19:38:27

怎么样:

var typeActions = new Dictionary<Type,Action<Object>>();
typeActions.Add(typeof(Type1), obj => DoType1((Type1)obj));
typeActions.Add(typeof(Type2), obj => DoType2((Type2)obj));

collection.Foreach(obj => typeActions[obj.GetType()](obj));

此代码未经测试(直接在浏览器中输入)。

What about something like:

var typeActions = new Dictionary<Type,Action<Object>>();
typeActions.Add(typeof(Type1), obj => DoType1((Type1)obj));
typeActions.Add(typeof(Type2), obj => DoType2((Type2)obj));

collection.Foreach(obj => typeActions[obj.GetType()](obj));

This code is untested (typed directly into the browser).

你的背包 2024-12-14 19:38:27

您的里程可能会有所不同。

Dictionary<Type, Action<object>> typeMap = new Dictionary<Type, Action<object>>();
typeMap[typeof(Type1)] = item => DoType1(item as Type1);
typeMap[typeof(Type2)] = item => DoType2(item as Type2);

var typeToActionQuery =
  from item in source
  let type = item.GetType()
  where typeMap.ContainsKey(type)
  select new
  {
    input = item;
    method = typeMap[type]
  };

foreach(var x in typeToActionQuery)
{
  x.method(x.input);
}

这是考虑派生类型的匹配查询的版本(注意,一个项目可能与超过 1 个类型匹配,因此会处理多次)。

var typeToActionQuery =
  from item in source
  from kvp in typeMap
  where kvp.Key.IsInstanceOfType(item)
  select new
  {
    input = item;
    method = kvp.Value
  };

Your mileage may vary.

Dictionary<Type, Action<object>> typeMap = new Dictionary<Type, Action<object>>();
typeMap[typeof(Type1)] = item => DoType1(item as Type1);
typeMap[typeof(Type2)] = item => DoType2(item as Type2);

var typeToActionQuery =
  from item in source
  let type = item.GetType()
  where typeMap.ContainsKey(type)
  select new
  {
    input = item;
    method = typeMap[type]
  };

foreach(var x in typeToActionQuery)
{
  x.method(x.input);
}

Here's a version of the matching query which considers derived types (Note, an item may be matched to more than 1 type, and therefore handled multiple times).

var typeToActionQuery =
  from item in source
  from kvp in typeMap
  where kvp.Key.IsInstanceOfType(item)
  select new
  {
    input = item;
    method = kvp.Value
  };
何以心动 2024-12-14 19:38:27

在我看来,如果您只需将“item.GetType() == typeof( Type1 )”替换为“item is Type1”,您的 foreach 循环就会足够简单。

It seems to me that if you just replace "item.GetType() == typeof( Type1 )" with "item is Type1", your foreach loop will be simple enough.

琉璃梦幻 2024-12-14 19:38:27

默认情况下不是。尝试反应式扩展Elevate

Reactive Extensions 和 Elevate 都包含 ForEach 实现。两者都有相当多的方法来扩展 linq 的功能。

您不会找到 ForEachType,但会找到 ForEach(Rx 或 Elevate)和 OfType<> 。 (Linq) 会给你你想要的。

Not by default. Try Reactive Extensions or Elevate

The Reactive Extensions and Elevate both contain a ForEach implementation. Both have quite a few methods that extend the functionality of linq.

You won't find a ForEachType, but ForEach (Rx or Elevate) and OfType<> (Linq) will give you what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文