Please consider the following snippet from the implementation of the interpreter template:
public override object Execute(Interpreter interpreter, object ctx) { var list = ctx as IEnumerable<string>; return (list != null) ? list.FirstOrDefault() : null; }
How about if I want to use the same function for integers?
public override object Execute(Interpreter interpreter, object ctx) { var list = ctx as IEnumerable<string>; if (list != null) return list.FirstOrDefault(); var list = ctx as IEnumerable<int>; return (list != null) ? list.FirstOrDefault() : null; }
What I wanted was something like:
public override object Execute(Interpreter interpreter, object ctx) { var list = ctx as IEnumerable; return (list != null) ? list.FirstOrDefault() : null; }
But Linq doesn't act on IEnumerables. Instead, to get to this solution, I would have to write something like:
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; }
Or use the general method:
public override T Execute<T>(Interpreter interpreter, object ctx) { var list = ctx as IEnumerable<T>; return (list != null) ? list.FirstOrDefault() : null; }
What violates the interpreter pattern (how it was implemented in this system). Covariance will also fail (at least in C # 3), although this will work, this would be the exact behavior I wanted:
public override object Execute(Interpreter interpreter, object ctx) { var list = ctx as IEnumerable<object>; return (list != null) ? list.FirstOrDefault() : null; }
So my question is: what's the best way to achieve intended behavior?
Addendum: digEmAll offers something like the following code:
var list = ctx as IEnumerable; return (list != null) ? list.Cast<object>().FirstOrDefault() : null;
This is a good answer for things like FirstOrDefault (). The problem is related to things like Reverse:
var list = ctx as IEnumerable; return (list != null) ? list.Cast<object>().Reverse() : null;
I could feed this method a List<int> , but I will return to List<object> . I know that there is no way to circumvent covariance. So I think digEmAll code is the best answer.
Thanks: -)