match value with
| :? list<#SomeType> as l -> l //Is it possible to match any list of a type derived from SomeType?
| _ -> failwith "doesn't match"
Respuesta
No, desafortunadamente no es posible hacer algo como esto: el CLR no proporciona ninguna forma eficiente de hacer ese tipo de prueba de tipo. Vea How to cast an object to a list of generic type in F# y F# and pattern matching on generics in a non-generic method implementing an interface para algunas soluciones (bastante feas).
Como ya se señaló, no hay forma de hacerlo directamente (la coincidencia de patrones solo puede vincular valores, pero no puede vincular nuevas variables de tipo). Además de la solución (más general) por kvb puede utilizar el hecho de que todas las colecciones de implementar no genérico IEnumerable
, para que pueda comprobar de este tipo:
match box value with
| :? System.Collections.IEnumerable as l when
// assumes that the actual type of 'l' is 'List<T>' or some other type
// with single generic type parameter (this is not fully correct, because
// it could be other type too, but we can ignore this for now)
typedefof<SomeType>.IsAssignableFrom
(value.GetType().GetGenericArguments().[0]) ->
l |> Seq.cast<SomeType>
| _ -> failwith "doesn't match"
El código prueba si el valor es una no genérico IEnumerable
y si el parámetro de tipo es subtipo de SomeType
. En ese caso, tenemos una lista de algún tipo derivado, por lo que podemos convertirlo a una secuencia de valores SomeType
(esto es ligeramente diferente de trabajar con la lista de valores de los tipos derivados, pero no debería importar para fines prácticos) .
Más tarde necesité algo similar para hacer coincidir las instancias de Lazy. Aquí está mi solución, en caso de que alguien lo encuentre útil.
let (|Lazy|_|) (value : obj) =
if box value <> null then
let typ = value.GetType()
if typ.IsGenericType && typ.GetGenericTypeDefinition() = typedefof<Lazy<_>> then
Some(typ.GetGenericArguments().[0])
else None
else None
Uso:
match value with
| Lazy typ when typeof<SomeType>.IsAssignableFrom(typ) -> (value :?> Lazy<_>).Value
| _ -> failwith "not an instance of Lazy<#SomeType>"
De acuerdo con la F# 2.0 specification, par. 14.5.2 (Resolviendo Subtipos de Restricciones), no funcionará, porque: "Los tipos genéricos F # no admiten la covarianza o la contravarianza".
el más limpio, pero eficaz:
let matchType<'T>() =
try
let o = Activator.CreateInstance<'T>()
match box o with
| :? Type1 -> printfn "Type1"
| :? Type2 -> printfn "Type2"
| _ -> failwith "unknown type"
with
| ex -> failwith "%s" (ex.ToString())
- 1. Obtiene el tipo real de un parámetro de objeto genérico
- 2. Sin el boxeo o el tipo de conversión de parámetros para el parámetro genérico Tipo
- 3. Creación método genérico y el uso de parámetro de tipo
- 4. Obtiene el tipo genérico para el parámetro java.util.Map
- 5. Upcasting con un parámetro de tipo genérico
- 6. Acceso a propiedades mediante el parámetro de tipo genérico
- 7. C#: ¿se usa el tipo de "auto" como parámetro genérico?
- 8. ¿Cómo convertir el puntero al tipo de parámetro genérico?
- 9. ¿Predeterminado para el tipo genérico?
- 10. El compilador de Scala no puede inferir el tipo de mezcla para la coincidencia de patrones
- 11. El parámetro de tipo no se extiende tipo dado
- 12. Tipo anulable como un parámetro genérico posible?
- 13. El tipo debe ser un tipo de referencia para usarlo como parámetro 'T' en el tipo o método genérico
- 14. Sin conversión de parámetros de tipo de cuadro o tipo para el parámetro Tipo genérico con Mono
- 15. ":" en el parámetro de tipo
- 16. Tipo genérico en el constructor
- 17. ¿Cómo obtener el tipo real de un tipo genérico?
- 18. ¿Cómo comparar el tipo de objeto con un tipo genérico, irrelevante para el argumento genérico?
- 19. Tipo de parámetro Tipo de
- 20. parámetro de tipo genérico y la sobrecarga del método anulable
- 21. Conversión de tipo genérico
- 22. Cómo especificar el parámetro para el método de extensión de tipo de lista genérico en C#
- 23. ¿Qué significa "salir" antes de un parámetro de tipo genérico?
- 24. usando AutoCompleteTextField en portillo sin cadena como el tipo genérico
- 25. C# El tipo genérico está encuadrado?
- 26. Definición del parámetro de tipo genérico limitado en C#
- 27. Usando un parámetro opcional de tipo System.Drawing.Color
- 28. Cómo detectar si el tipo es otro tipo genérico
- 29. diferencia entre el tipo genérico y comodín tipo
- 30. pasan enumeración de tipo genérico como parámetro (Java)
No es que supongo que importa, pero ¿por qué necesita para que coincida con una lista de algún tipo? Si la lista es homogénea, entonces simplemente puede procesar la lista elemento por elemento y eso está bien. Si la lista es heterogénea, entonces no puede considerar la lista como una unidad lógica de todos modos. ¿Cuál es el problema que estás tratando de resolver aquí? –
Supongo que debería haber usado mi código real. Solo estoy usando la lista por simplicidad. La pregunta es cómo hacer una coincidencia flexible en los parámetros de tipo. –
Daniel