En Scala, puede utilizar coincidencia de patrones para producir un resultado en función del tipo de la entrada. Por ejemplo:La implementación de coincidencia de patrones en C#
val title = content match {
case blogPost: BlogPost => blogPost.blog.title + ": " + blogPost.title
case blog: Blog => blog.title
}
En C#, me gusta lo ideal será capaz de escribir:
var title = Visit(content,
(BlogPost blogPost) => blogPost.Blog.Title + ": " + blogPost.Title,
(Blog blog) => blog.Title
);
Es esto posible? Cuando intenté escribirlo como un método único, no sé cómo especificar los genéricos. La siguiente aplicación le parece derecho, aparte de conseguir el tipo de corrector para permitir funciones que aceptan subtipos de T:
public TResult Visit<T, TResult>(T value, params Func<T, TResult>[] visitors)
{
foreach (var visitor in visitors)
{
if (visitor.Method.GetGenericArguments()[0].IsAssignableFrom(value.GetType()))
{
return visitor(value);
}
}
throw new ApplicationException("No match");
}
Lo más cerca que he recibido es añadir las funciones de un objeto de forma individual, y luego llamar a visitar en una valor:
public class Visitor<T, TResult>
{
private class Result
{
public bool HasResult;
public TResult ResultValue;
}
private readonly IList<Func<T, Result>> m_Visitors = new List<Func<T, Result>>();
public TResult Visit(T value)
{
foreach (var visitor in m_Visitors)
{
var result = visitor(value);
if (result.HasResult)
{
return result.ResultValue;
}
}
throw new ApplicationException("No match");
}
public Visitor<T, TResult> Add<TIn>(Func<TIn, TResult> visitor) where TIn : T
{
m_Visitors.Add(value =>
{
if (value is TIn)
{
return new Result { HasResult = true, ResultValue = visitor((TIn)value) };
}
return new Result { HasResult = false };
});
return this;
}
}
esto puede ser usado de esta manera:
var title = new Visitor<IContent, string>()
.Add((BlogPost blogPost) => blogPost.Blog.Title + ": " + blogPost.Title)
.Add((Blog blog) => blog.Title)
.Visit(content);
alguna idea de cómo hacer esto con una sola llamada al método?
poco se parece a un diccionario donde la clave es un tipo y el valor es una función ... – Roly
¿Está utilizando C# 3 o 4?En C# 4, el tipo de Func es contravariante en sus tipos de parámetros formales, lo que le brinda más flexibilidad en las conversiones. –
@Eric Lippert: en este caso, * creo que * realmente quiero la covarianza en lugar de la contravariancia. Quiero aceptar funciones que podrían no ser capaces de aceptar parámetros de tipo T (mientras que normalmente querría aceptar cualquier función que acepte parámetros de tipo T, que incluye funciones que aceptan parámetros de tipo U, donde T <: U) –