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:
Funcou 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 outparâ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);