我有一个名为Rows
的自定义类,它实现了IEnumerable<Row>
。我经常在Rows
个实例上使用LINQ查询:
Rows rows = new Rows { row1, row2, row3 };
IEnumerable<Row> particularRows = rows.Where<Row>(row => condition);
我希望能够做到以下几点:
Rows rows = new Rows { row1, row2, row3 };
Rows particularRows = (Rows)rows.Where<Row>(row => condition);
但是,我得到一个“System.InvalidCastException:无法转换'WhereEnumerableIterator1 [NS.Row]'类型的对象来键入'NS.Rows'”。我的Rows
构造函数有IEnumerable<Row>
,所以我可以这样做:
Rows rows = new Rows { row1, row2, row3 };
Rows particularRows = new Rows(rows.Where<Row>(row => condition));
然而,这似乎很笨重,我希望能够IEnumerable<Row>
成为Rows
,因为Rows
实施IEnumerable<Row>
。有什么想法吗?
答案 0 :(得分:4)
救援的延伸方法。
public static Rows ToRows(this IEnumerable<Row> source)
{
return new Rows(source);
}
行特殊行=行。其中(...)。ToRows();
“施法”不适合这个问题。每个Rows
都是IEnumerable<Row>
,但不是每个IEnumerable<Row>
都是Rows
答案 1 :(得分:2)
如果对象实际上是该类的实例,则只能将对象强制转换为特定的类。
在您的情况下,从LINQ调用获得的IEnumerable<Row>
不是Rows
实例,并且.Net运行时无法将其神奇地转换为Rows
实例。< / p>
相反,您需要创建一个从Rows
创建新IEnumerable<Row>
实例的函数。该函数可能应该是构造函数重载或扩展方法。
顺便说一句,请注意,标准的.Net命名约定表明您的Rows
类实际上应该被称为RowCollection
。
答案 2 :(得分:1)
虽然Rows
可能会实现IEnumerable<Row>
并不意味着任何IEnumerable<Row>
都是Rows
,所以编译器不能让你做出这样的假设。 / p>
答案 3 :(得分:1)
你必须记住,虽然你可以建立继承链(Row - &gt; IEnumerable),但没有可靠的方法来抛弃继承链。
请考虑以下事项:
List<Row> rows = new List<Row>();
// Fill the list
IEnumerable<Row> rowsAsEnumerable = (IEnumerable<Row>)rows;
Rows realRows = (Rows)rowsAsEnumerable;
由于rowsAsEnumerable永远不是Rows
对象,系统如何处理强制转换?
答案是它不可能,因为即使Rows对象始终是IEnumerable,IEnumerable也不总是Rows对象。
<强>更新强>
由于我不喜欢做一个梦想破碎机,我会重新改变其他人所说的话。
您可以使用简单的Extension方法从示例中使事情变得更清晰:
public static Rows ToRows(this IEnumerable<Row> rowsAsEnum)
{
return new Rows(rowsAsEnum);
}
现在您可以将通话更改为:
Rows particularRows = rows.Where<Row>(row => condition).ToRows();
答案 4 :(得分:0)
这有用吗?
Rows particularRows = (Rows)(rows.Where<Row>(row => condition).ConvertAll(r=>(Row)r));
您还可以为上面添加扩展方法包装器(这将是最干净的解决方案),因此您可以执行以下操作:
Rows particularRows = rows.Where<Row>(row => condition).ToRows();
答案 5 :(得分:0)
基本上你在这里提出的任何解决方案都将涉及环绕构造函数,它包含一个IEnumerable
我的原始答案定义了转换解决方案(但我无法编译并看到错误)。
我要做的是为IEnumerable定义一个扩展方法:
public static Rows ToRows(this IEnumerable<Row> rows)
{
return new Rows(rows);
}
然后你可以非常干净地使用它:
public void Foo(IEnumerable<Row> rows)
{
Rows r = rows.Where(r => condition).ToRows();
}
答案 6 :(得分:-1)
您需要在班级中定义explicit cast:
public class Rows : IEnumerable<Row>
{
public static explicit operator MyType(IEnumerable<Row> x)
{
return new Rows(x); // using your constructor
}
}
这将告诉C#允许你的演员:
Rows particularRows = (Rows)rows.Where<Row>(row => condition);