2009-04-19 20 views
30

Yani Pro buYeni Action() ve bir lambda arasındaki fark nedir?

Action action = new Action(()=>_myMessage = "hello"); 

Refactor gibi bir şey yazarken! Bu gereksiz bir temsilci yaratılması gibi vurgular ve bana

Action action =() => _myMessage="hello"; 

bunu kısaltmak için olanak Ve bu genellikle iyi çalışıyor. Genellikle, ancak her zaman değil. İlk versiyon çalışmalarında geçen Burada

IMethodOptions<T> Do(Delegate action); 

, ama ikinci yapmaz: Örneğin, Rhino Mocks Do adında bir uzantısı yöntemi vardır. Buradaki kapaklar tam olarak neler oluyor?

+4

Kişisel İkinci kod bloğu derleme değil:

(sizin Rhino Mocks örneğin) bir yöntem çağrılırken bu yuvarlak almak için en basit yolu döküm etmektir. Bu iletiyi "örtülü olarak yazılmış yerel bir değişkene lambda ifadesi atanamıyor" iletisi alıyorum. Ancak, "var" kelimesini "Action" ile değiştirirsem yapar. –

+1

Evet, haklısınız, örtülü bir değişkene atanamaz, onu düzenlerim. –

cevap

47

ilk sürüm etkili yapıyor:

Action tmp =() => _myMessage = "hello"; 
var action = new Action(tmp); 

sizsiniz yaşamaya devam edip sorun bu konuda ayrıntılı bir tartışma için

, sen konudaki Eric Lippert blog girişlerini okumalısınız derleyicinin lambda ifadesinin ne tür bir delege (veya ifade ağacı) dönüştürüleceğini bilmesi gerekir.

var action =() => _myMessage="hello"; 

aslında derleme değil - bu parametre ve dönüş değeri ya da (muhtemelen string olduğu) _myMessage aynı dönüş türü biriyle herhangi temsilci türü olabilir: bu yüzden. Örneğin, bütün bunlar geçerlidir:

Action action =() => _myMessage="hello"; 
Func<string> action =() => _myMessage="hello"; 
MethodInvoker action =() => _myMessage="hello"; 
Expression<Action> =() => _myMessage="hello"; 
// etc 

Nasıl C# derleyicisi olması gerekiyordu ne tür action işe yarayabilir, bu var ile beyan ederse?

methodOptions.Do((Action) (() => _myMessage = "hello")); 
+3

VB.Net, kullanıma dayalı olarak temsilci türleri oluşturarak bunu başarabiliyor.VB zaten void ve void olmayan dönen fonksiyonlar (alt ve fonksiyon) arasında ayrım yaptığı için farklılaşmayı kolaylaştırır. – JaredPar

+4

"C# derleyicisi, var ile ne tür bir eylemin yapılması gerektiğine nasıl karar verebilir?" Basit: işlev türleri birinci sınıf yapısal türler olmalı, bu adlandırılmış temsilci öğeleri değil. Ve tırnak kodu böyle belirtilmelidir. Ama sanırım bu artık değişmeyecek :). – MichaelGG

+1

Bence böyle bir kadro yapmak için lambda çevresinde ek bir parantez çiftine ihtiyacınız var. –

8

İkinci satırı gerçekten derlediniz doğruladınız mı? C#, örtülü olarak yazılan bir değişkene (CS0815) bir lambda ifadesi atamayı desteklemediği için derlenmemelidir. Bu satır VB.Net'te çalışacaktır, çünkü anonim delege oluşturmayı desteklemektedir (VB 9.0'dan başlayarak).

Rhino Mocks sürümü aynı nedenle derlenmez, ikinci satır derlenmemelidir. C#, lambda ifadesi için otomatik olarak bir tür çıkarmayacaktır. Lambda ifadeleri, yerine getirilmesi amaçlanan temsilci türünü belirlemek mümkün olan bir bağlamda kullanılmalıdır. İlk satır harika çalışır çünkü amaçlanan tip açıktır: Eylem. Rhino Mocks sürümü çalışmıyor çünkü Temsilci daha soyut bir temsilci türüne benziyor. Action veya Func gibi somut bir delege türü olmalıdır. http://blogs.msdn.com/ericlippert/archive/2007/01/11/lambda-expressions-vs-anonymous-methods-part-two.aspx

İlgili konular