... или, как я могу фильтровать последовательность классов с помощью интерфейсов, которые они реализуют?
Скажем, у меня есть последовательность объектов, которые наследуются от Foo, a seq<#Foo>
. Другими словами, моя последовательность будет содержать один или несколько из четырех разных подклассов Foo.
Каждый подкласс реализует другой независимый интерфейс, который не имеет ничего общего с интерфейсами, реализованными другими подклассами.
Теперь мне нужно отфильтровать эту последовательность только для элементов, реализующих определенный интерфейс.
Версия С# проста:
void MergeFoosIntoList<T>(IEnumerable<Foo> allFoos, IList<T> dest)
where T : class
{
foreach (var foo in allFoos)
{
var castFoo = foo as T;
if (castFoo != null)
{
dest.Add(castFoo);
}
}
}
Я мог бы использовать LINQ из F #:
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
System.Linq.Enumerable.OfType<'a>(foos)
|> Seq.iter dest.Add
Однако я чувствую, что должен быть более идиоматический способ его достижения. Я думал, что это сработает...
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
foos
|> Seq.choose (function | :? 'a as x -> Some(x) | _ -> None)
|> Seq.iter dest.Add
Однако, компилятор жалуется на :? 'a
- рассказывая мне:
Это принуждение или тест типа времени выполнения от типа "b" до "a" включает неопределенный тип на основе информации до этой точки программы. Тестирование типа времени выполнения не допускается для некоторых типов. Нужны дополнительные аннотации.
Я не могу понять, что добавить дополнительные аннотации типов. Нет никакой связи между интерфейсом 'a
и #Foo
, за исключением того, что один или несколько подклассов Foo реализуют этот интерфейс. Кроме того, нет никакой связи между различными интерфейсами, которые могут быть переданы как 'a
, за исключением того, что все они реализованы подклассами Foo.
Я с нетерпением ожидаю, когда ударяю себя в голову, как только один из вас добрых людей укажет на очевидную вещь, которую я пропустил.