2014-01-08 2 views
2

Например, возьмем следующий фрагмент кода:Зачем нужно определять параметризованное лямбда-выражение при указании объекта состояния?

var task = Task.Factory.StartNew(state => Greet("Hello"), "Greeting"); 

Я пытаюсь понять, почему есть необходимость передать «приветствие» с параметром state.

Почему это не могло быть так:

var task = Task.Factory.StartNew(()=>Greet("Hello"), "Greeting"); 
+0

Тогда что будет с государством? – SLaks

+1

'state' содержит текущее состояние. Вы можете использовать его значение в своем лямбда-вызове – knittl

+0

@knittl А я вижу, я подозревал, что, возможно, дело, большое спасибо. – Isomorph

ответ

3

Это единственные методы, определенные в TaskFactory, который принимает только два параметра, а также object state в качестве второго параметра.

public Task StartNew(Action<object> action, object state); 
public Task<TResult> StartNew<TResult>(Func<object, TResult> function, object state); 

Как вы можете видеть Action<object> потребности одного параметра, передаваемые в, а также Func<object, TResult> требует один параметр типа object, но в вашем случае, если вы не удовлетворены ни один из них так компилятор не устраивает.

var task = Task.Factory.StartNew(()=>Greet("Hello"), "Greeting"); 

Это не может быть ни преобразованы в Func<object, TResult> ни Action<object> action.

+0

Большое спасибо Шрирам. – Isomorph

1

Поскольку TaskFactory.StartNew<TResult> Method (Func<TResult>) должен возвращать результат, и учитывая, что лямбда-выражение вычисляется из справа налево, чтобы определить результат вам нужно состояние определить тип результата в Func<object, TResult> должен получить объект в качестве первого аргумента и возвращает результат

+0

Компилятор почти умный по типу вывода, это не так, здесь нет соответствующего разрешения перегрузки !. отправьте мой ответ для получения более подробной информации. –

1

Лучше думать об этом список этот

foreach(var s in myList) 
    { 
      Print(s); 
    } 

эквивалентно

myList.ForEach(s => Print(s)); 

Вам не нужно использовать с, но вы должны дать ему имя

2

Это оптимизация. Рассмотрим это, выделяющий замыкание:

MyState s; 
var task = Task.Factory.StartNew(() => Greet(s.Greeting)); 

Хотя это один будет использовать кэшированные делегат, как он ничего не захватывает:

MyState s; 
var task = Task.Factory.StartNew(o => Greet(((MyState)o).Greeting), s); 

Еще реже, но равноценны использование в том, что объект будет назначен до IAsyncResult.AsyncState имущество с возвратом Task.

+0

Неправильно. Нет такой оптимизации, проверьте мой ответ для деталей. –

+0

Оптимизация реальна, но да, его код, как указано, был неправильным. –

1

Here вы можете увидеть перегруженные версии StartNew method.You используют this версии:

public Task StartNew(Action<Object> action,Object state) 

Согласно документации:

состояние: Объект, содержащий данные, которые будут использоваться в действие делегат.

Вы хотите этого, но нет перегруженной версии так:

public Task StartNew(Action action,Object state) 

Итак, когда вы указываете состояние параметра, который нужно использовать Action<Object>.

Смежные вопросы