Uma vez compilado, existe uma diferença entre:
delegate { x = 0; }
e
() => { x = 0 }
?
Uma vez compilado, existe uma diferença entre:
delegate { x = 0; }
e
() => { x = 0 }
?
Respostas:
Resposta curta: não.
Resposta mais longa que pode não ser relevante:
Func
ou Action
), receberá um delegado anônimo.Edit: Aqui estão alguns links para expressões.
Gosto da resposta de Amy, mas achei que seria pedante. A pergunta diz: "Uma vez compilado" - o que sugere que ambas as expressões tenham sido compilados. Como eles poderiam compilar, mas com um sendo convertido em um delegado e outro em uma árvore de expressão? É complicado - você precisa usar outro recurso de métodos anônimos; o único que não é compartilhado por expressões lambda. Se você especificar um método anônimo sem especificar uma lista de parâmetros , ele será compatível com qualquer tipo de delegado retornando nulo e sem nenhum out
parâmetro. Armado com esse conhecimento, devemos ser capazes de construir duas sobrecargas para tornar as expressões completamente inequívocas, mas muito diferentes.
Mas um desastre acontece! Pelo menos com o C # 3.0, não é possível converter uma expressão lambda com um corpo de bloco em uma expressão - nem converter uma expressão lambda com uma atribuição no corpo (mesmo que seja usada como valor de retorno). Isso pode mudar com o C # 4.0 e o .NET 4.0, que permitem que mais seja expresso em uma árvore de expressão. Então, em outras palavras, com os exemplos que o MojoFilter deu, os dois quase sempre serão convertidos na mesma coisa. (Mais detalhes em um minuto.)
Podemos usar o truque de delegar parâmetros se mudarmos os corpos um pouco:
using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
int x = 0;
Foo( () => x );
Foo( delegate { return x; } );
}
static void Foo(Func<int, int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
static void Foo(Expression<Func<int>> func)
{
Console.WriteLine("I suspect the lambda expression...");
}
}
Mas espere! Podemos diferenciar os dois mesmo sem usar árvores de expressão, se formos espertos o suficiente. O exemplo abaixo usa as regras de resolução de sobrecarga (e o truque de correspondência de delegado anônimo) ...
using System;
using System.Linq.Expressions;
public class Base
{
public void Foo(Action action)
{
Console.WriteLine("I suspect the lambda expression...");
}
}
public class Derived : Base
{
public void Foo(Action<int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
}
class Test
{
static void Main()
{
Derived d = new Derived();
int x = 0;
d.Foo( () => { x = 0; } );
d.Foo( delegate { x = 0; } );
}
}
Ai. Lembre-se de crianças, toda vez que você sobrecarrega um método herdado de uma classe base, um gatinho começa a chorar.
delegate { ... }
é o mesmo que - este último é compatível apenas com um tipo de delegado sem parâmetros. delegate() { ... }
Nos dois exemplos acima, não há diferença, zero.
A expressão:
() => { x = 0 }
é uma expressão Lambda com corpo de instrução, portanto, não pode ser compilada como uma árvore de expressão. Na verdade, nem compila porque precisa de um ponto e vírgula após 0:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Amy B está correta. Observe que pode haver vantagens em usar árvores de expressão. O LINQ to SQL examinará a árvore de expressão e a converterá em SQL.
Você também pode fazer truques com lamdas e árvores de expressão para passar efetivamente os nomes dos membros da classe para uma estrutura de uma maneira segura para refatoração. Moq é um exemplo disso.
Há uma diferença
Exemplo:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
E substituo por lambda: (erro)
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Alguns princípios aqui.
Este é um método anônimo
(string testString) => { Console.WriteLine(testString); };
Como os métodos anônimos não têm nomes, precisamos de um representante no qual possamos atribuir esses dois métodos ou expressões. por exemplo
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
O mesmo com a expressão lambda. Geralmente precisamos de um delegado para usá-los
s => s.Age > someValue && s.Age < someValue // will return true/false
Podemos usar um delegado func para usar esta expressão.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);