C# 在泛型集合中使用LINQ 请从解释器模式的实现中考虑下面的代码段: public override object Execute(Interpreter interpreter, object ctx) { var list = ctx as IEnumerable<string>; return (list != null) ? list.FirstOrDefault() : null; }

C# 在泛型集合中使用LINQ 请从解释器模式的实现中考虑下面的代码段: public override object Execute(Interpreter interpreter, object ctx) { var list = ctx as IEnumerable<string>; return (list != null) ? list.FirstOrDefault() : null; },c#,linq,C#,Linq,但Linq不会对IEnumerables采取行动。相反,为了得到这个解决方案,我不得不写下如下内容: public override object Execute(Interpreter interpreter, object ctx) { var list = ctx as IEnumerable; return (list != null) ? list.FirstOrDefault() : null; } public override object Execute(In

但Linq不会对IEnumerables采取行动。相反,为了得到这个解决方案,我不得不写下如下内容:

public override object Execute(Interpreter interpreter, object ctx) {
    var list = ctx as IEnumerable;
    return (list != null) ? list.FirstOrDefault() : null;
}
public override object Execute(Interpreter interpreter, object ctx) {
    var list = ctx as IEnumerable;
    if (list != null) foreach(var i in list) { yield return i; return; }
    return null;
}
或使用一般方法:

public override T Execute<T>(Interpreter interpreter, object ctx) {
    var list = ctx as IEnumerable<T>;
    return (list != null) ? list.FirstOrDefault() : null;
}
public override T Execute(解释器、对象ctx){
var list=ctx作为IEnumerable;
return(list!=null)?list.FirstOrDefault():null;
}
这将打破解释器模式(因为它是在这个系统中实现的)。协方差也会失败(至少在C#3中是如此),尽管它会起作用,但这正是我想要的行为:

public override object Execute(Interpreter interpreter, object ctx) {
    var list = ctx as IEnumerable<object>;
    return (list != null) ? list.FirstOrDefault() : null;
}
public override object Execute(解释器、对象ctx){
var list=ctx作为IEnumerable;
return(list!=null)?list.FirstOrDefault():null;
}
所以,我的问题是:实现预期行为的最佳方式是什么


附录:DigeMail建议使用以下代码:

var list = ctx as IEnumerable;
return (list != null) ? list.Cast<object>().FirstOrDefault() : null;
var list=ctx作为IEnumerable;
返回(列表!=null)?list.Cast().FirstOrDefault():null;
对于FirstOrDefault()之类的东西,这是一个很好的答案。问题来自于逆向操作:

var list = ctx as IEnumerable;
return (list != null) ? list.Cast<object>().Reverse() : null;
var list=ctx作为IEnumerable;
返回(列表!=null)?list.Cast().Reverse():null;
我可以给这个方法提供一个
列表
,但我会得到一个
列表
。我知道,没有办法避开协方差。所以我想DigeMail代码是目前为止最好的答案



谢谢:-)

像这样的东西能满足你的需要吗

public override object Execute(Interpreter interpreter, object ctx) {
    var nonGenericlist = ctx as IEnumerable;
    if (nonGenericlist == null)
       return null;
    var list = nonGenericlist.Cast<object>();
    return (list != null) ? list.FirstOrDefault() : null;
}
public override object Execute(解释器、对象ctx){
var nonGenericlist=ctx作为IEnumerable;
如果(非通用列表==null)
返回null;
var list=nongenericslist.Cast();
return(list!=null)?list.FirstOrDefault():null;
}

如果代码符合您的要求,那么不要太担心破坏设计模式。设计模式是解决特定问题的工具。如果无法将解决方案放入模式中,则该模式不是正确的解决方案。如果工具箱中的每个工具都是某种锤子,那么每个解决方案都可以归结为“用锤子敲击”。有时,正确的解决方法是使用scredriver,甚至发明一种新工具。

似乎您希望在不定义所涉及类型的同时获得typesafety和LINQ支持—这在C中是无法做到的

一个选项是提供
Execute
的重载,而不是使用
object ctx
是否可以将适当的
IEnumerable
作为参数

例如,您可能有几个重载:

public override object Execute(Interpreter interpreter, IEnumerable<int> ctx)
public override object Execute(Interpreter interpreter, IEnumerable<string> ctx)
public override object Execute(Interpreter interpreter, IEnumerable<...> ctx)
针对IEnumerable重新实现所有LINQ将不会有趣。。。或者在某些情况下很容易。最好的方法是创建一个适配器,使您能够将
IEnumerable
视为
IEnumerable
——然后,无论您处理的是值类型序列还是引用类型序列,都可以使用它:

public static IEnumerable<object> AsObjectSequence( this IEnumerable sequence )
{
    foreach( object x in sequence )
        yield return x;
}
公共静态IEnumerable ASObject序列(此IEnumerable序列)
{
foreach(对象x按顺序排列)
收益率x;
}
编辑:事实证明,这在原则上相当于使用:

sequence.Cast<object>()
sequence.Cast()

所以yoy可能想使用它,因为它更简洁、更直接地内置到LINQ中。

事实上,它会的。同时,我们也提出了你的解决方案。我不知道对集合的每个元素进行强制转换时会对性能产生什么影响,但我会接受您的答案,除非出现更好的答案。强制转换()使用不同的执行方式,因此仅在需要时进行强制转换,在这种情况下,您最多可以进行一次强制转换。我知道;-)这不是所谓的“打破模式”的问题;更重要的是,整个系统依赖于对“对象”的操作,我不想破坏这个特定的实现。
public static IEnumerable<object> AsObjectSequence( this IEnumerable sequence )
{
    foreach( object x in sequence )
        yield return x;
}
sequence.Cast<object>()