【问题标题】:In C#, how can I convert my array from IEnumerable<IMyInterface> to IEnumerable<T>?在 C# 中,如何将数组从 IEnumerable<IMyInterface> 转换为 IEnumerable<T>?
【发布时间】:2017-01-05 00:53:14
【问题描述】:

在 C# 中,我想采用类型为“T”的数组我知道“T”支持接口“IMyInterface”并且:

  1. 将其转换为“IMyinterface”数组
  2. 在该数组上调用将过滤列表的方法
  3. 将其转换回原来的 T 型列表。

上面的 1 和 2 工作正常,但我在第 3 步遇到了问题。

这是我的代码:

IEnumerable<IMyInterface> castedArray = originalTypedArray as IEnumerable<IMyInterface>;

if (castedArray != null)
{
    var filteredArray = castedArray.Where(r => r.Ids.Contains(MyId)).ToList();

     IEnumerable<T> castedBackToOriginalTypeArray = filteredArray as IEnumerable<T>;
     if (castedBackToOriginalTypeArray == null)
     {
          current = new List<T>();
     }
     else
     {
        current = castedBackArray;
     }

     // I need to cast back, because only my Type T has the .Id property
     List<int> ids = current.Select(r => r.Id).ToList();
 }

问题出在这一行:

 IEnumerable<T> castedBackToOriginalTypeArray = filteredArray as IEnumerable<T>;

这似乎总是返回 null(而不是过滤后的数组转换回 IEnumerable

关于我可能做错了什么以及如何正确地将接口数组转换回类型 T 数组的任何建议?

【问题讨论】:

  • 在没有 IEnumerable 的情况下,从 T 转换到 IMyInterface 是否有效?
  • 你为什么需要投射?不能过滤一下原来的IEnumerable&lt;MyInterface&gt;吗?
  • @LucMorin - 我正在对 IEnumerable 进行过滤,但我需要将其转换回原始类型,因为我的下一行代码取决于它。我已将问题更新为更清楚
  • @kat1330 - 转换为 IMyInterface 的数组适用于上面的代码
  • 如果你不使用 ToList(),过滤后的数组应该已经是 IEnumerable,不需要再次转换。

标签: c# arrays casting ienumerable


【解决方案1】:

这对我有用:

public class A : IA {

}


public interface IA {

}

List<A> l = new List<A> { new A(), new A(), new A() };
IEnumerable<IA> ias = l.Cast<IA>();
IEnumerable<A> aTypes = ias.Cast<A>();

【讨论】:

  • 无需迭代整个集合来转换每个对象。如果集合包含 不是 T 的内容(以及 as 转换返回 null 的原因),这也会崩溃
  • @Rob OP 专门说:I want to take an array of Type "T" where I know "T" supports the interface "IMyInterface" 那它为什么会崩溃。
  • 因为“过滤”可能会在集合中添加一些内容。这里没有类型安全。事实上,如果您可以证明集合中仅包含T,则实际上不需要演员表。
  • 肯定使用OfType&lt;T&gt;“解决”了选角问题。它不仅会将过滤后的列表返回为IEnumerable&lt;T&gt;,而且还会忽略不属于T 类型的项目
【解决方案2】:

要么您不需要将其强制转换为 IEnumerable&lt;IMyInterface&gt;,要么运行时已正确阻止您编写错误代码。

我们举个小例子:

void SomeMethod<T>(IEnumerable<T> originalTypedArray, int MyId) 
    where T : class, IMyInterface
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is important 
{
    if (originalTypedArray != null)
    {
        var filteredArray = originalTypedArray.Where(r => r.Ids.Contains(MyId));

        // No need to cast to `IEnumerable<T>` here - we already have ensured covariance
        // is valid in our generic type constraint
        DoSomethingExpectingIEnumerableOfIMyInterface(filteredArray);
    }
}
void DoSomethingExpectingIEnumerableOfIMyInterface(IEnumerable<IMyInterface> src)
{
    foreach (var thing in src)
    {

    }
}

但是,如果您没有将集合作为IEnumerable&lt;T&gt; 获取,则运行时正确地使强制转换失败:

void SomeMethod<T>(IEnumerable<IMyInterface> originalTypedArray, int MyId)

假设Apple : IMyInterface,我们可以给它一堆IEnumerable&lt;Apple&gt;。然后你尝试将它转换为IEnumerable&lt;T&gt; T = Banana 和繁荣,代码损坏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    相关资源
    最近更新 更多