оператор yield return не может появляться в ограничении блока try / catch
2665 просмотра
4 ответа
Эти два метода практически одинаковы, но первый не может быть скомпилирован. Я не могу понять причину этого ограничения
/// <summary>
/// Dynamically loads all document extractors from implementation assemblies into an enumeration
/// </summary>
private static IEnumerable<IDocumentExtractor> EnumerateInstances()
{
IEnumerable<Type> types = EnumerateTypes();
foreach(Type type in types)
{
try
{
IDocumentExtractor extractor = Activator.CreateInstance(type) as IDocumentExtractor;
yield return extractor;
}
catch
{
_log.WarnFormat("Type {0} couldn't be instanced.", type.Name);
}
}
}
И версия, которая на самом деле компилируется без проблем:
/// <summary>
/// Dynamically loads all document extractors from implementation assemblies into an enumeration
/// </summary>
private static IEnumerable<IDocumentExtractor> EnumerateInstances()
{
IEnumerable<Type> types = EnumerateTypes();
foreach (Type type in types)
{
IDocumentExtractor extractor = null;
try
{
extractor = Activator.CreateInstance(type) as IDocumentExtractor;
}
catch
{
_log.WarnFormat("Type {0} couldn't be instanced.", type.Name);
}
if (extractor != null)
yield return extractor;
}
}
Автор: bevacqua
Источник
Размещён: 12.11.2019 09:49
Ответы (4)
7 плюса
Вы можете получить ответ на этот вопрос в серии Эрика Липперта о блоках итераторов. В частности, ознакомьтесь с публикацией под названием « Блоки итераторов», часть пятая: «Push против Pull» . Серия из семи частей начинается с блоков итераторов, часть первая .
Автор: jason Размещён: 03.11.2011 02:256 плюса
Эрик Липперт подробно объясняет это в своей серии статей о блоках итераторов . Начните снизу и продолжайте свой путь вверх, и не пропускайте ничего, пока не достигнете нужного момента.
Я не буду пытаться объяснить это дальше - я процитирую часть поста 5 , который на самом деле посвящен try
блокам, которые имеют catch
блоки (пост 4 рассказывает о catch
самих блоках, но это другой вопрос).
Автор: Jon Skeet Размещён: 03.11.2011 02:28Так что, если блок try имеет подвох?
У оригинальных дизайнеров C # 2.0 - и помните, это задолго до моего пребывания в команде - была большая дискуссия по этому поводу. Дискуссия, которая повторялась в миниатюре, когда я отправил им электронное письмо с просьбой обосновать это решение. Есть три основных положения:
Ни в коем случае не допускайте возврат доходности в блоках try. (Или блоки, которые являются сахарами для блоков try, например, с использованием блоков.) Используйте другой механизм, отличный от «finally», чтобы выразить идею «это код, который вы запускаете, когда вызывающая сторона выключает перечисление».
Разрешить возврат урожая во всех блоках try.
Разрешить возвращение yield в блоках try, в которых есть блоки finally, но не в том случае, если в них есть блоки catch.
[Надрез]
Недостатком (3) является то, что правило кажется произвольным и странным - пока вы не прочитаете пять ненужных записей в блоге, которые объясняют, что на самом деле думала команда разработчиков.
Очевидно, они выбрали (3), и теперь вы знаете, почему.
0 плюса
Но вы можете написать:
private static IEnumerable<IDocumentExtractor> EnumerateInstances()
{
IEnumerable<Type> types = EnumerateTypes();
foreach(Type type in types)
{
var oResult = Test(type);
if (oResult != null)
{
yield return oResult;
}
}
}
private static IDocumentExtractor Test(Type type)
{
try
{
IDocumentExtractor extractor = Activator.CreateInstance(type) as IDocumentExtractor;
return extractor;
}
catch
{
return null;
//_log.WarnFormat("Type {0} couldn't be instanced.", type.Name);
}
}
Просто Visual Studio не хочет делать эту работу, поэтому вы должны сделать это самостоятельно (ленивый компилятор)
Автор: Toto Размещён: 03.11.2011 02:32-1 плюса
public static IEnumerable IListFind(IEnumerable list, ConditionHandler handler, EventHandler errorHandler = null, DateTime? started = null)
{
try
{
if (started == null) { started = DateTime.Now; };
return IListFindInternal(list, handler);
}
catch
{
if (DateTime.Now.Subtract(started.Value).TotalSeconds < 30)
{
if (errorHandler != null) { errorHandler(list, EventArgs.Empty); };
return IListFind(list, handler, errorHandler, started);
}
else
{
return null;
}
}
}
public static IEnumerable IListFindInternal(IEnumerable list, ConditionHandler handler) { foreach (object item in list) { if (handler(item)) { yield return item; } } }
Автор: Basil
Размещён: 16.02.2012 05:58
Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- c# Datatable против Dataset
- c# Setting Objects to Null/Nothing after use in .NET
- c# Конвертировать целые числа в записанные числа
- c# Почему я не могу иметь абстрактные статические методы в C #?
- c# Как я могу оценить код C # динамически?
- c# Как заставить кнопку выглядеть так, как будто она нажата?
- c# Цикл C # - разрыв против продолжения
- c# Почему в C # нельзя хранить объект List <string> в переменной List <object>
- c# В чем разница между строкой и строкой в ??C #?
- c# Что означает атрибут Enum [Flags] в C #?
- c# Лучший способ получить доступ к элементу управления в другой форме в Windows Forms?
- c# Преобразование общего типа из строки
- c# C # 3.0 авто-свойства - полезно или нет?
- c# Как удалить дубликаты из массива C #?
- c# Как можно создать документ Word в C #?