Czy po skompilowaniu istnieje różnica między:
delegate { x = 0; }
i
() => { x = 0 }
?
Czy po skompilowaniu istnieje różnica między:
delegate { x = 0; }
i
() => { x = 0 }
?
Odpowiedzi:
Krótka odpowiedź: nie.
Dłuższa odpowiedź, która może nie być istotna:
Func
lub Action
), otrzymasz anonimowego delegata.Edycja: Oto kilka linków do wyrażeń.
Podoba mi się odpowiedź Amy, ale myślałem, że będę pedantyczny. Pytanie mówi: „Po to jest skompilowany” - co sugeruje, że oba wyrażenia nie został opracowany. Jak oba można skompilować, ale jeden z nich jest konwertowany na delegata, a drugi na drzewo wyrażeń? To trudne - musisz użyć innej funkcji anonimowych metod; jedyny, który nie jest współdzielony przez wyrażenia lambda. Jeśli określisz sposób anonimowy bez podania listy parametrów w ogóle nie jest kompatybilny z dowolnym typem delegat powrocie nieważne i bez żadnych out
parametrów. Uzbrojeni w tę wiedzę powinniśmy być w stanie skonstruować dwa przeciążenia, aby wyrażenia były całkowicie jednoznaczne, ale bardzo różne.
Ale katastrofa uderza! Przynajmniej w języku C # 3.0 nie można przekonwertować wyrażenia lambda z treścią bloku na wyrażenie - nie można też przekonwertować wyrażenia lambda z przypisaniem w treści (nawet jeśli jest ono używane jako wartość zwracana). Może się to zmienić w C # 4.0 i .NET 4.0, które pozwalają wyrazić więcej w drzewie wyrażeń. Innymi słowy, z przykładami podanymi przez MojoFilter, te dwa prawie zawsze zostaną przekonwertowane na to samo. (Więcej szczegółów za minutę.)
Możemy użyć sztuczki delegowania parametrów, jeśli zmienimy nieco ciała:
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...");
}
}
Ale poczekaj! Możemy je rozróżnić nawet bez użycia drzewek wyrażeń, jeśli jesteśmy wystarczająco przebiegli. W poniższym przykładzie użyto reguł rozwiązywania problemów z przeciążeniem (i anonimowej sztuczki polegającej na dopasowaniu pełnomocnika) ...
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; } );
}
}
Auć. Pamiętajcie, dzieciaki, za każdym razem, gdy przeładujecie metodę odziedziczoną z klasy podstawowej, mały kotek zaczyna płakać.
delegate { ... }
to nie to samo co delegate() { ... }
- to ostatnie jest kompatybilne tylko z bezparametrowym typem delegata.
W dwóch powyższych przykładach nie ma różnicy, zero.
Ekspresja:
() => { x = 0 }
jest wyrażeniem Lambda z treścią instrukcji, więc nie można go skompilować jako drzewa wyrażeń. W rzeczywistości nawet się nie kompiluje, ponieważ potrzebuje średnika po 0:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Amy B ma rację. Zauważ, że korzystanie z drzew wyrażeń może mieć zalety. LINQ to SQL zbada drzewo wyrażeń i skonwertuje je na SQL.
Możesz także grać w sztuczki z lamdami i drzewami ekspresji, aby skutecznie przekazywać nazwiska członków klasy do struktury w sposób bezpieczny dla refaktoryzacji. Moq jest tego przykładem.
Jest różnica
Przykład:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
I zamieniam na lambda: (błąd)
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Kilka podstawowych informacji tutaj.
To jest anonimowa metoda
(string testString) => { Console.WriteLine(testString); };
Ponieważ anonimowe metody nie mają nazw, potrzebujemy delegata, w którym możemy przypisać obie te metody lub wyrażenia. na przykład
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
To samo z wyrażeniem lambda. Zwykle potrzebujemy delegata, aby z nich skorzystać
s => s.Age > someValue && s.Age < someValue // will return true/false
Możemy użyć delegata func, aby użyć tego wyrażenia.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);