Convertir un predicado<t> a un Func<t, bool=""></t,></t>
Tengo una clase con un miembro Predicate
que me gustaría usar en una expresión Linq:
using System.Linq;
class MyClass
{
public bool DoAllHaveSomeProperty()
{
return m_instrumentList.All(m_filterExpression);
}
private IEnumerable m_instrumentList;
private Predicate m_filterExpression;
}
Como leí eso...Predicate
es [...] totalmente equivalente a Func
"Ve aquí.Espero que esto funcione, ya que All
toma como argumento: Func
.
Sin embargo, recibo el error:
Argument 2: cannot convert from 'System.Predicate' to 'System.Type'
¿Hay una manera de convertir el predicado a un argumento de que esta función se tragará?
Pregunta hecha hace 9 años, 8 meses, 23 días - Por codemaster89
8 Respuestas:
-
Los dos tipos representan la misma firma lógica, pero eso no significa que sean sólo interchangables. Una asignación recta no funcionará, por ejemplo - pero usted puede crear un nuevo
Func
de laPredicate
. Código de muestra:Predicate
pred = x => x.Length > 10; // Func func = pred; // Error Func func = new Func (pred); // Okay Esto es como tener dos
enum
tipos con los mismos valores - se puede convertir entre ellos, pero tiene que hacerlo explícitamente. Todavía son tipos separados.En su caso, esto significa que podría escribir:
public bool DoAllHaveSomeProperty() { return m_instrumentList.All(new Func
(m_filterExpression)); } El enfoque de expresión de lambda sugerido por otras respuestas también funcionará, por supuesto.
Respondida el Aug 27, 2014 a las 16:05 - por byteexplorer
Votos positivos: 0 | Votos negativos: 0 -
public bool DoAllHaveSomeProperty() { return m_instrumentList.All(i => m_filterExpression(i)); }
Respondida el Aug 27, 2014 a las 16:11 - por rubyrogue
Votos positivos: 0 | Votos negativos: 0 -
Puedes convertir un predicado a un método llamando a Invoke. Todos los delegados tienen a este miembro. Los delegados no tienen identidad estructural, pero los métodos se pueden convertir en delegados iguales. Esta fijación tiene un costo de rendimiento menor, ya que añade una capa extra de la indirecta. Sin embargo, la mayoría de las soluciones a este problema tienen ese problema. Eric Lippert habla de esto con más detalle en https://web.archive.org/web/20140625132124/http://blog.coverity.com/2014/06/18/delegates-estructura-identity/ .
En su caso específico, sustituya
return m_instrumentList.All(m_filterExpression);
conreturn m_instrumentList.All(m_filterExpression.Invoke);
Código de muestra que demuestra el problema real.
void Main() { Predicate
t1 = Foo; Func t2 = Foo; Predicate t3 = t2.Invoke; //Legal Func t4 = t1.Invoke; //Legal Predicate t5 = t2; //Illegal Func t6 = t1; //Illegal } bool Foo(int x) { return x > 20; } Respondida el Aug 27, 2014 a las 16:21 - por algorithmadept
Votos positivos: 0 | Votos negativos: 0 -
return m_instrumentList.All(i => m_filterExpression(i));
Respondida el Aug 27, 2014 a las 16:26 - por scriptsorcererf493
Votos positivos: 0 | Votos negativos: 0 -
Ya que hay muchas respuestas que añadiré una más solo para divertirme. Si desea que su código compila, puede utilizar métodos de extensión
//Original Code class MyClass4 { public bool DoAllHaveSomeProperty() { return m_instrumentList.All(m_filterExpression); } private IEnumerable
m_instrumentList; private Predicate m_filterExpression; } Añadir esta clase en el mismo espacio de nombres
public static class MyExtentions { public static bool All(this IEnumerable
enumer, Predicate pred) { return enumer.All(e => pred(e)); } } Respondida el Aug 27, 2014 a las 16:32 - por codemasterx
Votos positivos: 0 | Votos negativos: 0 -
Como dijo Brian, puedes convertir un predicado a un método a través de
Invoke
:public bool DoAllHaveSomeProperty() { return m_instrumentList.All(m_filterExpression.Invoke); }
Respondida el Aug 27, 2014 a las 16:37 - por codemaestro
Votos positivos: 0 | Votos negativos: 0 -
Para convertir un
Predicate<t>
a unFunc<t, bool>
, puedes hacerlo utilizando el constructor deFunc<t, bool>
que recibe como parámetro elPredicate<t>
. Aquí te dejo un ejemplo de cómo modificar tu código para lograrlo:csharp using System; using System.Linq; using System.Collections.Generic; class MyClass { public bool DoAllHaveSomeProperty() { return m_instrumentList.All(new Func
(m_filterExpression)); } private IEnumerable m_instrumentList; private Predicate m_filterExpression; } public class instrument { // Definir la clase instrument con sus propiedades } Al crear un nuevo
Func<instrument, bool>
y pasarle elPredicate<instrument>
como parámetro en el constructor, estás convirtiendo efectivamente elPredicate<instrument>
en una función que puede ser usada en la expresión LINQ. De esta manera, el error que estás viendo debería desaparecer y podrás usar tu predicado en el métodoAll
correctamente.Respondida el Aug 28, 2014 a las 16:03 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Sí, puedes convertir un
Predicate<T>
aFunc<T, bool>
usando una conversión lambda. Aquí tienes un ejemplo:csharp Predicate
predicate = i => i.SomeProperty; // Convertir el predicado a un Func Func func = predicate.Convert (); // Usar el Func en la expresión LINQ bool result = m_instrumentList.All(func); El método
Convert
toma unPredicate<T>
como entrada y devuelve unFunc<T, bool>
que representa la misma lógica.También puedes utilizar un método de extensión para simplificar la conversión:
csharp public static Func
ToFunc (this Predicate predicate) { return i => predicate(i); } ... // Usar el método de extensión Func func = m_filterExpression.ToFunc(); // Usar el Func en la expresión LINQ bool result = m_instrumentList.All(func); Este método de extensión convierte un
Predicate<T>
en unFunc<T, bool>
creando una expresión lambda que llama al predicado.Respondida el Aug 28, 2014 a las 16:17 - por Gemini
Votos positivos: 0 | Votos negativos: 0