.NET-итератор для переноса метания API - PullRequest
7 голосов
/ 28 октября 2010

У меня есть класс с API, который позволяет мне запрашивать объекты, пока он не выдаст IndexOutOfBoundsException.

Я хочу обернуть его в итератор, чтобы иметь возможность писать более чистый код.Однако мне нужно перехватить исключение, чтобы прекратить итерации:

static IEnumerable<object> Iterator( ExAPI api ) {
    try {
       for( int i = 0; true; ++i ) {
          yield return api[i]; // will throw eventually
       }
    } 
    catch( IndexOutOfBoundsException ) {
       // expected: end of iteration.
    }
}

Но ...

При использовании с выражением, оператор return yield не может появляться в блоке catch илив блоке try, который имеет одно или несколько предложений catch.Для получения дополнительной информации см. Операторы обработки исключений (C # Reference) .Statements (C # Reference).(из msdn )

Как мне все еще обернуть этот API?

Ответы [ 5 ]

14 голосов
/ 28 октября 2010

Вам просто нужно переместить оператор yield return за пределы блока try, например:

static IEnumerable<object> Iterator( ExAPI api ) {
   for( int i = 0; true; ++i ) {
        object current;
        try {
            current = api[i];
        } catch(IndexOutOfBoundsException) { yield break; }

        yield return current;
    } 
}
4 голосов
/ 28 октября 2010

Вы можете заключить простую операцию получения объекта в отдельную функцию.Вы можете перехватить там исключение:

bool TryGetObject( ExAPI api, int idx, out object obj )
{
    try
    {
        obj = api[idx];
        return true;
    }
    catch( IndexOutOfBoundsException )
    {
        return false;
    }        
}

Затем вызвать эту функцию и завершить, если необходимо:

static IEnumerable<object> Iterator( ExAPI api )
{
   bool abort = false;

    for( int i = 0; !abort; ++i )
    {
        object obj;
        if( TryGetObject( api, i, out obj ) )
        {
            yield return obj;
        }
        else
        {
            abort = true;
        }
    }
}
0 голосов
/ 28 октября 2010
    static IEnumerable<object> Iterator(ExAPI api)
    {
        int i = 0;
        while (true)
        {
            Object a;
            try
            {
                a = api[i++];
            }
            catch (IndexOutOfBoundsException)
            {
                yield break;
            }
            yield return a;
        }
    }
0 голосов
/ 28 октября 2010

Если вы вообще не можете проверить границы объекта, вы можете сделать что-то вроде этого

static IEnumerable<object> Iterator( ExAPI api )
{
 List<object> output = new List<object>();
    try
 {
  for( int i = 0; true; ++i )
   output.Add(api[i]);
    } 
    catch( IndexOutOfBoundsException )
 {
  // expected: end of iteration.
    }
 return output;
}

хотя теперь, когда я смотрю здесь, ответ выше, я верю. Один СЛакс выложил.

0 голосов
/ 28 октября 2010

Просто измените код:

static IEnumerable<object> Iterator( ExAPI api ) {
    bool exceptionThrown = false;
    object obj = null;
    for( int i = 0; true; ++i ) {
        try {
            obj = api[i];
        }
        catch( IndexOutOfBoundsException ) {
            exceptionThrown = true;
            yield break;
        }

        if (!exceptionThrown) {
            yield return obj;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...