Після її складання, чи є різниця між:
delegate { x = 0; }
і
() => { x = 0 }
?
Після її складання, чи є різниця між:
delegate { x = 0; }
і
() => { x = 0 }
?
Відповіді:
Коротка відповідь: ні.
Більш довга відповідь, яка може не бути актуальною:
Func
або Action
), ви отримаєте анонімного делегата.Редагувати: Ось декілька посилань для виразів.
Мені подобається відповідь Емі, але я думав, що буду педантичним. Питання говорить: «Після того, як він складений» - що говорить про те , що обидва вирази було скомпільовано. Як вони могли обидва складати, але один перетворювався на делегата, а інший - у дерево виразів? Це складне - вам доведеться використовувати ще одну функцію анонімних методів; єдиний, який не поділяється лямбда-виразами. Якщо вказати анонімний метод без зазначення списку параметрів на все він поєднає з будь-яким типом делегата повернення недійсним і без будь - яких out
параметрів. Озброївшись цими знаннями, ми повинні мати можливість побудувати два перевантаження, щоб зробити вирази абсолютно однозначними, але дуже різними.
Але катастрофа вражає! Принаймні, за допомогою C # 3.0, ви не можете перетворити лямбда-вираз із тілом блоку в вираз - а також не можна перетворити лямбда-вираз із призначенням у тілі (навіть якщо воно використовується як повернене значення). Це може змінитися за допомогою C # 4.0 та .NET 4.0, які дозволяють виражати більше у дереві виразів. Отже, іншими словами, з прикладами, які MojoFilter наводив, вони майже завжди перетворюються на одне і те ж. (Детальніше за хвилину.)
Ми можемо використовувати трюк параметрів делегування, якщо трохи змінити тіла:
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...");
}
}
Але зачекайте! Ми можемо розмежовувати це двоє, навіть не використовуючи дерева виразів, якщо ми досить хитрі. У наведеному нижче прикладі використовуються правила роздільної здатності перевантаження (та фокус відповідного анонімного делегата) ...
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; } );
}
}
Ой. Пам’ятайте, діти, щоразу, коли ви перевантажуєте метод, успадкований від базового класу, маленьке кошеня починає плакати.
delegate { ... }
це не те саме, що delegate() { ... }
- останній сумісний лише з типом делегата без параметрів.
У двох вище прикладах немає різниці, нуль.
Вираз:
() => { x = 0 }
- це вираз лямбда з тілом оператора, тому його неможливо скласти як дерево виразів. Насправді він навіть не компілюється, оскільки йому потрібна крапка з комою після 0:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
Емі В правильно. Зауважте, що використання дерев виразів може мати переваги. LINQ в SQL вивчить дерево виразів і перетворить його в SQL.
Ви також можете грати в трюки з ламдами та деревами виразів, щоб ефективно передавати імена членів класу до рамки безпечним способом рефакторингу. Мок - приклад цього.
Є різниця
Приклад:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
І я замінюю лямбда: (помилка)
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
Деякі основи тут.
Це анонімний метод
(string testString) => { Console.WriteLine(testString); };
Оскільки анонімні методи не мають імен, нам потрібен делегат, в якому ми можемо призначити обидва ці методи або вирази. напр
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
Те саме з висловом лямбда. Зазвичай для їх використання нам потрібен делегат
s => s.Age > someValue && s.Age < someValue // will return true/false
Ми можемо використовувати функцію делегата, щоб використовувати цей вираз.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);