Проблема с обработкой исключений для IEnumerable <T>, это зависимо от ленивости

Существует множество способов достигнуть этой цели, некоторые более ясны, чем другие. Для каждого из моих примеров, 'Верных', означает, что строка передала, допустимо, 'Ложный' означает, что это содержит недопустимые символы.

, В первую очередь, существует наивный подход:

import string
allowed = string.letters + string.digits + '_' + '-'

def check_naive(mystring):
    return all(c in allowed for c in mystring)

Тогда существует использование регулярного выражения, можно сделать это с re.match (). Обратите внимание, что '-' должен быть в конце [] иначе, он будет использоваться в качестве разделителя 'диапазона'. Также отметьте $, что означает 'конец строки'. Другие ответы, отмеченные в этом вопросе, используют класс специального символа, '\w', я всегда предпочитаю использовать явное использование диапазона класса символов [], потому что легче понять, не имея необходимость искать краткое руководство, и легче к особому случаю.

import re
CHECK_RE = re.compile('[a-zA-Z0-9_-]+ 

Другое решение отметило, что можно сделать обратное соответствие с регулярными выражениями, я включал это здесь теперь. Обратите внимание, что [^...] инвертирует класс символов, потому что ^ используется:

CHECK_INV_RE = re.compile('[^a-zA-Z0-9_-]')
def check_inv_re(mystring):
   return not CHECK_INV_RE.search(mystring)

можно также сделать что-то хитрое с объектом 'набора'. Взгляните на этот пример, который удаляет из исходной строки все символы, которые позволяются, оставляя нас с набором, содержащим любого a) ничто, или b) незаконные символы от строки:

def check_set(mystring):
    return not set(mystring) - set(allowed)
) def check_re(mystring): return CHECK_RE.match(mystring)

Другое решение отметило, что можно сделать обратное соответствие с регулярными выражениями, я включал это здесь теперь. Обратите внимание, что [^...] инвертирует класс символов, потому что ^ используется:

CHECK_INV_RE = re.compile('[^a-zA-Z0-9_-]')
def check_inv_re(mystring):
   return not CHECK_INV_RE.search(mystring)

можно также сделать что-то хитрое с объектом 'набора'. Взгляните на этот пример, который удаляет из исходной строки все символы, которые позволяются, оставляя нас с набором, содержащим любого a) ничто, или b) незаконные символы от строки:

def check_set(mystring):
    return not set(mystring) - set(allowed)
7
задан Max Galkin 15 November 2009 в 22:36
поделиться

4 ответа

Настоящая проблема здесь - отложенное выполнение. В случае проверки аргументов вы можете сделать это, добавив второй метод:

IEnumerable<int> LazyThrow() {
     // TODO: check args, throwing exception
     return LazyThrowImpl();
}
IEnumerable<int> LazyThrowImpl() {
    // TODO: lazy code using yield
}

Исключения случаются; даже для неотложного результата (например, List ) вы можете получить ошибки (возможно, если другой поток изменяет список во время итерации). Вышеупомянутый подход позволяет сделать как можно больше заранее, чтобы уменьшить неожиданные побочные эффекты yield и отложенного выполнения.

10
ответ дан 6 December 2019 в 14:05
поделиться

Теоретически согласен с вашим коллегой. Если есть некоторая «работа» для создания результатов, и эта работа может вызвать исключение, и вам не нужна ленивая оценка, то действительно, если результат будет ленивым, это только усложнит ситуацию.

Однако на практике есть « Вы никак не можете взглянуть на возвращаемый тип и вывести что-нибудь слишком полезное. Даже если вы сделали возвращаемый тип ReadonlyCollection, он все равно может задержать оценку и выбросить, например (ReadonlyCollection не запечатан, поэтому подкласс может явно реализовать интерфейс IEnumerable и делать дурацкие вещи).

В конце дня , система типов .Net не поможет вам много рассуждать об исключительном поведении большинства объектов.

Я бы, по сути, все же предпочел бы возвращать ReadonlyCollection, а не IEnumerable, но поскольку он предоставляет более полезные методы ( как O (1) доступ к n-му элементу) по сравнению с IEnumerable. Если вы собираетесь создать коллекцию манифестов, поддерживаемую массивом, вы также можете вернуть потребителям полезные аспекты этого. (Вы также можете просто вернуть «свежий» массив, которым должен владеть вызывающий.

3
ответ дан 6 December 2019 в 14:05
поделиться

Я не согласен с вашим коллегой. Документация по методу должна соответствовать стандартному документу, в котором могут возникать исключения. Объявление типа возврата как IEnumerable не делает его доступным только для чтения. Будет ли он доступен только для чтения, зависит от фактической реализации возвращаемого интерфейса. Вызывающий не должен полагаться на то, что он доступен для записи, но это сильно отличается от коллекции, доступной только для чтения

2
ответ дан 6 December 2019 в 14:05
поделиться

Подобная проблема обсуждалась в сообщениях Эрика Липперта:

http://blogs.msdn.com/ericlippert/archive/2007/09 /05/psychic-debugging-part-one.aspx[1296 visiblehttp://blogs.msdn.com/ericlippert/archive/2007/09/06/psychic-debugging-part-two.aspx

Однако я не будет рассматривать это как аргумент против IEnumerable в целом. Честно говоря, в большинстве случаев, когда перечисляемая мной коллекция выдает исключение, я не знаю, что с ним делать, и в основном он переходит к какому-то глобальному обработчику ошибок. Конечно, я согласен с тем, что момент создания исключения может сбивать с толку.

0
ответ дан 6 December 2019 в 14:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: