2009-02-19 28 views
29

Tipo de expresión condicional no se puede determinar porque no hay una conversión implícita entre 'expresión lambda' y 'expresión lambda'C#: ¿Sin conversión implícita entre 'expresión lambda' y 'expresión lambda'?

Say whaat? ¿Podría alguien explicarme este error de compilación? Este es el código que lo produce:

protected override Func<System.IO.Stream> GetStream() 
    { 
     return someBool 
      ?() => EmbeddedResourceExtractor.GetFile("SomeFile1.ext") 
      :() => EmbeddedResourceExtractor.GetFile("SomeFile2.ext"); 
    } 

Esto no es así:

protected override Func<System.IO.Stream> GetStream() 
    { 
     return() => EmbeddedResourceExtractor.GetFile("SomeFile1.ext"); 
    } 

Y tampoco lo haga lo siguiente:

protected override Func<System.IO.Stream> GetStream() 
    { 
     if(someBool) 
      return() => EmbeddedResourceExtractor.GetFile("SomeFile1.ext"); 
     return() => EmbeddedResourceExtractor.GetFile("SomeFile2.ext"); 
    } 
+3

http://stackoverflow.com/questions/263151/lambdas-and-the-ternary-operator-weird-issue – user17541

Respuesta

41

El tipo de la expresión condicional debe inferirse como una las expresiones enteras y lambda siempre tienen que convertirse a un delegado específico o tipo de árbol de expresiones.

En sus dos últimos ejemplos, el compilador sabe a qué intenta convertir la expresión lambda. En el primer ejemplo, primero intenta resolver el tipo de expresión condicional completa.

Un yeso en una de las ramas sería suficiente, sin embargo:

protected override Func<Stream> GetStream() 
{ 
    return someBool 
     ? (Func<Stream>) 
      (() => EmbeddedResourceExtractor.GetFile("SomeFile1.ext")) 
     :() => EmbeddedResourceExtractor.GetFile("SomeFile2.ext"); 
} 

solución de Sergio (ahora eliminado, pero se incluye a continuación) trabajará si que estaban contentos de evaluar someBool en el momento de la función es llamado:

protected override Func<Stream> GetStream() 
{ 
    return() => someBool 
      ? EmbeddedResourceExtractor.GetFile("SomeFile1.ext") 
      : EmbeddedResourceExtractor.GetFile("SomeFile2.ext"); 
} 

Dependiendo de la temporización, hay todo tipo de formas diferentes de corregir el ejemplo que ha dado, por ejemplo

protected override Func<Stream> GetStream() 
{ 
    string name = someBool ? "SomeFile1.ext" : "SomeFile2.ext"; 
    return() => EmbeddedResourceExtractor.GetFile(name); 
} 

Supongo que su código real es más complicado.

Es una pena que, en cierto modo, la inferencia de C# no sea más poderosa, pero ya es bastante complicada.

+2

Con la excepción de tener que envolver la primera rama entre paréntesis, funcionó sí ... Espero que puede hacer que la inferencia del tipo C# sea aún mejor en el futuro. Aunque, ya es bastante agradable =) – Svish

+0

Buenas opciones, en realidad no había pensado en ninguna de ellas. Pero eso lo hará más claro sí :) – Svish

+0

¿crees que esto es algo que mejorarían alguna vez? Este problema (y otros similares a él, como no poder usar ** var ** con lambdas) realmente parece una vergüenza. –