example - remarks c#
¿Por qué no puedes usar la función anon con un parámetro dinámico? (2)
¿Cuál es el tipo estático de lamba a => a.address_1
? Puede sentirse tentado de decir que es un Func<dynamic, dynamic>
. Pero recuerda:
Una expresión lambda es una función anónima que puede usar para crear delegados o tipos de árboles de expresiones.
Entonces tal vez sea una Expression<Func<dynamic, dynamic>>
. Un lamda en sí mismo no tiene un solo tipo estático.
Ahora, normalmente, la inferencia de tipo daría cuenta de que está pasando el lamba a una función que toma un Func
y se convertirá en un delegado en tiempo de compilación. Sin embargo, cuando realiza una llamada con argumentos dinámicos, la llamada al método se distribuye dinámicamente .
Si tiene una llamada a un método con un argumento dinámico, se distribuye dinámicamente, punto. Durante el enlace en tiempo de ejecución, todos los tipos estáticos de sus argumentos son conocidos (énfasis mío), y los tipos se seleccionan para los argumentos dinámicos en función de sus valores reales.
Por lo tanto, el hecho de que su método tome un Func
no se tiene en cuenta, ya que la llamada al método real no se determina hasta el tiempo de ejecución, por lo que no hay inferencia de tipo.
Para que esto se compile, tendrás que convertir tu lamba a Func<dynamic, string>
como se muestra a continuación:
return ifNotNull<string>(firstAddress, new Func<dynamic, string>((a) => a.address_1), null);
Ahora se conoce el tipo estático de tu lamda.
Acabo de toparme con esto hoy
Una función anónima o grupo de métodos no se puede usar como un valor constituyente de una operación enlazada dinámicamente.
cuando intentas hacer
static R ifNotNull<R>(dynamic o, Func<dynamic, R> returnFunc, R otherwise) {
return ReferenceEquals(null, o) ? otherwise : returnFunc(o);
}
y usarlo con
dynamic firstAddress = ...;
return ifNotNull<string>(firstAddress, (a) => a.address_1, null)
Ahora la mayoría de las limitaciones de la dinámica tienen sentido para mí: no se puede usar un método de extensión porque ¿cómo se supone que el compilador debe decidir a qué estático compilarlo? Pero no entiendo esto aquí. ¿Dónde entra la confusión? ¿Cuál es exactamente la limitación?
Quise decir que necesitas lanzar el método lambda
a la expresión de espera que deseas. Entonces funcionará bien.
Me gusta esto:
return ifNotNull(firstAddress, (Func<dynamic, string>)((a) => a.address_1), null);