2008-09-12 15 views
21

Tüm anonim özelliklerden yeniyim ve biraz yardıma ihtiyacım var. İşe aşağıdaki aldık:Bu temsilci anonim bir yöntemle veya lambdaya dönüştürün

public void FakeSaveWithMessage(Transaction t) 
{ 
    t.Message = "I drink goats blood"; 
} 

public delegate void FakeSave(Transaction t); 

public void SampleTestFunction() 
{ 
    Expect.Call(delegate { _dao.Save(t); }).Do(new FakeSave(FakeSaveWithMessage)); 
} 

Ama bu tamamen çirkin olduğunu ve bunu mümkün olup olmadığını anonim yöntem, hatta bir lambda olması Do içini istiyorum.

Expect.Call(delegate { _dao.Save(t); }).Do(delegate(Transaction t2) { t2.Message = "I drink goats blood"; }); 

ve

Expect.Call(delegate { _dao.Save(t); }).Do(delegate { t.Message = "I drink goats blood"; }); 

ama bunlar bana

bir temsilci türü değil çünkü 'System.Delegate' yazın anonim yöntemi dönüştürülemez ** derleme hataları verin: Denedim .

Neyi yanlış yapıyorum? Çünkü Mark Ingram yayınlanmıştır ne


, kimse açıkça söylenir da, bu yapmaktır, en iyi cevap gibi görünüyor:

public delegate void FakeSave(Transaction t); 

Expect.Call(delegate { _dao.Save(t); }).Do(new FakeSave(delegate(Transaction t2) { t.Message = expected_msg; })); 

cevap

27

Bu bilinen bir hata iletisidir. Daha ayrıntılı bir tartışma için aşağıdaki bağlantıyı kontrol edin.

http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/

Temelde sadece anonim temsilci (lambda ifade) önünde bir döküm koymak gerekir.

durumda bağlantı şimdiye kadar burada, iner yazının bir kopyasıdır:

Onlar Anonim Yöntemler değil Anonim Delegeler vardır.
Biz zor olmak istiyorum çünkü sadece konuşan bir nokta değil staceyw1

tarafından 22 Aralık 2007 tarihinde gönderildi. Tam olarak neler olduğu konusunda bize neden olur. Açık olmak gerekirse, anonim delege olarak gibi bir şey yoktur. mevcut değil (henüz değil). Bunlar "Anonim Yöntemler" - dönemdir. 'un bunları nasıl düşündüğümüz ve bunları hakkında nasıl konuştuğumuz önemlidir. anonim yöntem deyimine bir göz atalım "delegate() {…}". Bu aslında iki farklı işlemidir ve bu şekilde 'u düşündüğümüzde, tekrar ile karıştırılmayacağız. derleyicisinin yapacağı ilk şey, temsilcisinin imzası olarak temsilci imzasını kullanarak kapaklar altında anonim yöntemini oluşturur. demek doğru değildir, yöntem "adsız" dır çünkü bir ada sahip ve derleyici onu atar. Sadece normal görünümden gizlenmiştir. yapacağı sonraki şey, yöntemi sarmak için gerekli türünün temsilci nesnesini oluşturur. Bu , temsilci çıkarımı olarak adlandırılır ve bu karışıklığın kaynağı olabilir. Çalıştırmak için için derleyici, oluşturulacak delege türünü anlayabilen olmalıdır (diğer bir ifadeyle). Bilinen bir beton tipi olması için 'a sahiptir. Nedenini görmek için kod yazalım.

private void MyMethod() 
{ 
} 

derlemek yok: derleyici herhangi temsilci türünü tahmin edemez çünkü

1) Delegate d = delegate() { };      // Cannot convert anonymous method to type ‘System.Delegate’ because it is not a delegate type 
2) Delegate d2 = MyMethod;       // Cannot convert method group ‘MyMethod’ to non-delegate type ‘System.Delegate’ 
3) Delegate d3 = (WaitCallback)MyMethod; // No overload for ‘MyMethod’ matches delegate ‘System.Threading.WaitCallback’ 

Satır 1 derlemek etmez. İstediğimiz imzayı açıkça görebilir, ancak derleyicinin görebileceği somut delege türü yoktur. Bu, bizim için tür delege anonim bir tür oluşturabilir, ancak böyle çalışır. Satır 2, benzer bir nedenle derlemiyor. derleyici yöntemi imza bilse bile rağmen, biz bunu temsilci türü veren değildir ve sadece ( olabilir bu ne yan etkileri olmayan) çalışmak olacağını birini seçmek gitmiyor. Satır 3, , imzasının farklı bir imzası olan (WaitCallback alır ve nesnesi gibi) farklı bir imzası olan yöntemle hatalı bir şekilde eşleşmediğinden, çalışmaz.

derler: Buna karşılık

4) Delegate d4 = (MethodInvoker)MyMethod; // Works because we cast to a delegate type of the same signature. 
5) Delegate d5 = (Action)delegate { };    // Works for same reason as d4. 
6) Action d6 = MyMethod;        // Delegate inference at work here. New Action delegate is created and assigned. 

bu eser. Satır 1, delege türünün kullanılmasını istediği için derleyiciye çalışır; bu nedenle, eşleşir, böylece çalışır. Satır 5 aynı nedenden dolayı çalışır. Not: Parentesiz "delegate" özel formunu kullandık. Derleyici, imzasını kalıbın içinden alır ve anonim yöntemini, türünde, türünde, ertelenmiş temsilci olarak aynı anonim yöntemle oluşturur. Satır 6, MyMethod() ve Eylem'in aynı imzasını kullanması nedeniyle çalışır.

Umarım bu yardımcı olur.

Ayrıca bakınız: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/

+1

İyi linke ama (o lambda sözdizimi ile yaptığı gibi) hala neden * derleyici automagicallylar döküm gelmez * anlamıyorum –

+0

Bağlantı bozuk. –

+0

Hala benim için çalışıyor musun? –

0

gibi bir şey deneyin:

Expect.Call(delegate { _dao.Save(t); }).Do(new EventHandler(delegate(Transaction t2) { t2.CheckInInfo.CheckInMessage = "I drink goats blood"; })); 

Not Delegenin etrafında eklenen EventHandler.

DÜZENLEME: EventHandler ve temsilci işlev imzaları aynı olmadığından çalışmayabilir ... Sorunun alt kısmına eklediğiniz çözüm tek yol olabilir.

Alternatif olarak, bir genel temsilci türü oluşturabilirsiniz: temsilci İşlem özgü değildir

public delegate void UnitTestingDelegate<T>(T thing); 

Böylece.

3

Mark söylediklerin.

Sorun, bir Delegate parametresi almasıdır. Derleyici, anonim yöntemleri Delege'e dönüştüremez; yalnızca bir "temsilci türü" yani Delege'den türetilen bir beton türü.

Eğer bu Do işlevi <>, Eylem <,> ... gibi aşırı yüklemeler yapmış olsaydı, aldatmaya gerek duymazdınız.

1

Sorun, temsilci tanımınızla ilgili değil, Do() yönteminin parametresi System.Delegate türünde ve derleyici tarafından oluşturulan delege türü (FakeSave), dolaylı olarak System.Delegate'e dönüştürülmez.

deneyin anonim temsilci önünde bir atışı ekliyor:

Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; }); 
+0

Bu, temsilci çalışmıyor {} anonim bir işlevdir - bir tür değil. System.Delegate, bildirilen tüm delege türlerinin örtük tabanı olan soyut temel sınıftır. Burada temsilci kelimesinin 3 farklı kullanımı var! Herhangi bir delege türünü (EvantHandler, Action, Func gibi) Delege'e gönderebilirsiniz, ancak öncelikle bir temsilci türü oluşturmanız gerekir! –

İlgili konular