+ //
+ // Ok, we can access it, now make sure that we can do something
+ // with this `GetEnumerator'
+ //
+
+ Type return_type = mi.ReturnType;
+ if (mi.ReturnType == TypeManager.ienumerator_type ||
+ TypeManager.ienumerator_type.IsAssignableFrom (return_type) ||
+ (!RootContext.StdLib && TypeManager.ImplementsInterface (return_type, TypeManager.ienumerator_type))) {
+ //
+ // If it is not an interface, lets try to find the methods ourselves.
+ // For example, if we have:
+ // public class Foo : IEnumerator { public bool MoveNext () {} public int Current { get {}}}
+ // We can avoid the iface call. This is a runtime perf boost.
+ // even bigger if we have a ValueType, because we avoid the cost
+ // of boxing.
+ //
+ // We have to make sure that both methods exist for us to take
+ // this path. If one of the methods does not exist, we will just
+ // use the interface. Sadly, this complex if statement is the only
+ // way I could do this without a goto
+ //
+
+ if (return_type.IsInterface && return_type.IsGenericType) {
+ enumerator_type = return_type;
+ if (!FetchGetCurrent (ec, return_type))
+ get_current = new PropertyExpr (
+ ec, TypeManager.ienumerator_getcurrent, loc);
+ if (!FetchMoveNext (ec, return_type))
+ move_next = TypeManager.bool_movenext_void;
+ return true;
+ }
+
+ if (return_type.IsInterface ||
+ !FetchMoveNext (ec, return_type) ||
+ !FetchGetCurrent (ec, return_type)) {
+ enumerator_type = return_type;
+ move_next = TypeManager.bool_movenext_void;
+ get_current = new PropertyExpr (
+ ec, TypeManager.ienumerator_getcurrent, loc);
+ return true;
+ }