... или как отфильтровать последовательность классов по интерфейсам, которые они реализуют?
Допустим, у меня есть последовательность объектов, которые наследуются от Foo, a seq<#Foo>
. Другими словами, моя последовательность будет содержать один или несколько из четырех различных подклассов Foo.
Каждый подкласс реализует свой независимый интерфейс, который ничего не разделяет с интерфейсами, реализованными другими подклассами.
Теперь мне нужно отфильтровать эту последовательность до элементов, которые реализуют определенный интерфейс.
Версия C # проста:
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.
Я с нетерпением ожидаю удара головой, как только один из вас, добрых людей, заметит очевидную вещь, по которой я скучаю.