2010-10-29 13 views
7

Başka birinin buna rastlaması durumunda bunu paylaşacağımı düşündüm.
Bugün benzer bir şey yaptım ve bunun neden çalışma zamanında bir soruna neden olduğunu anlamaları biraz zaman aldı.VB.Net - "With" ve Kapaklar karıştırılmıyor

Bu kod:

Public Class foo 
    Public bar As String = "blah" 
End Class 

Public Sub DoInline() 
    Dim o As New foo 
    Dim f As Func(Of String) 
    With o 
    f = Function() .bar 
    End With 
    Try 
    Console.WriteLine(f.DynamicInvoke()) 
    Catch ex As Reflection.TargetInvocationException 
    Console.WriteLine(ex.InnerException.ToString) 
    End Try 
End Sub 

bir NullReferenceException atar. With, kapanışını geçici depolama alanı olarak kullanıyor ve “End With” ile kapanış değişkenini Nothing olarak ayarlıyor gibi görünüyor. İşte

RedGate yansıtıcı içinde o kod şudur:

Public Shared Sub DoInline() 
    Dim o As New foo 
    Dim $VB$Closure_ClosureVariable_7A_6 As New _Closure$__1 
    $VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = o 
    Dim f As Func(Of String) = New Func(Of String)(AddressOf $VB$Closure_ClosureVariable_7A_6._Lambda$__1) 
    $VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = Nothing 
    Try 
     Console.WriteLine(RuntimeHelpers.GetObjectValue(f.DynamicInvoke(New Object(0 - 1) {}))) 
    Catch exception1 As TargetInvocationException 
     ProjectData.SetProjectError(exception1) 
     Console.WriteLine(exception1.InnerException.ToString) 
     ProjectData.ClearProjectError 
    End Try 
End Sub 

$VB$Closure_ClosureVariable_7A_6.$VB$Local_VB$t_ref$L0 = Nothing 

Sadece "sorusu" Gerçekten sorabilir Bildirimi olduğu; Bu bir hata ya da bazı sebeplerden dolayı göremediğim garip bir tasarım kararı. Şu andan itibaren "With" özelliğini kullanmaktan kaçınacağım.

+0

haha, Ben sadece şunu anladım: D Şimdi neden olduğunu anlıyorum ama tamamen derler ki ... –

cevap

8

Bu davranış, "Tasarım" dır ve With ifadesinin genellikle yanlış anlaşılan bir ayrıntıdan kaynaklanır.

With ifadesi aslında bir ifadeyi argüman olarak alır ve doğrudan referans değildir (en yaygın kullanım durumlarından biri olsa bile). Dil özelliğinin Bölüm 10.3'ü, bir With bloğuna iletilen ifadenin yalnızca bir kez değerlendirildiğini ve With ifadesinin yürütülmesi için kullanılabileceğini garanti eder.

Bu, bir geçici kullanarak uygulanır. Bu nedenle, bir ifadesini bir With ifadesinin içinde yürütürken, orijinal değere erişmiyorsunuz, ancak orijinal değere işaret eden bir geçici. Aşağıdaki gibi diğer eğlenceli senaryolara izin verir.

Dim o as New Foo 
o.bar = "some value" 
With o 
    o = Nothing 
    Console.WriteLine(.bar) ' Prints "some value" 
End With 

With deyimi içinde sen o ameliyat olmayan ancak oldukça özgün ifadesi için geçici bir işaret için bu çalışır. Bu geçici sadece, With bildiriminin ömrü boyunca canlı olduğu garanti edilir ve bu nedenle de sonunda Nothing d olur.

Örneğinizde kapak doğru olarak geçici değeri yakalar. Bu nedenle, With bildirimi tamamlandıktan sonra geçici olarak Nothing olur ve kod uygun şekilde başarısız olur.

+0

Hem csauve kodunu hem de verdiğiniz örnekte derleme yapmasına izin verilmemelidir. –

+0

oh tamam, bu mantıklı olmaya başlıyor.Örneğindeki davranıştan haberdar oldum, daha önce hiç biriyle bir kapanış yapmayı denemedim. TEŞEKKÜRLER! – csauve

+0

"With" öğesinin geçici bir süre yarattığını biliyorum, ancak geçici olarak niçin iptal edileceği açık değil. Bir kapanış kapsam dışında kalan bir değişkene sahipse, değişken genellikle geçerli olmayacak mı? – supercat

1

Gerçekten gördüğüm tek bir hata var, derleyici bunun için bir hata oluşturmalıdır. Uygulaması zor olmamalı. Bunu bildirebilirsin connect.microsoft.com

+1

Lambdas, bir "With" bloğu içinde geçerli olarak oluşturulabilir ve kullanılabilir. Burada hata yapmak, bir hataya neden olmak için tamamen geçerli bir koda neden olur. True Vb.Net, "foreach" döngüsünde yineleme değişkenini yakalamak için benzer bir yöntem seçti. Ancak bu durumda, yanlış yapan birçok insan örneği vardı, bunun gerekli olduğunu hissettik. Bir uyarı olarak bunu yapmayı seçtik, böylece kullanıcılar bunu baskılayabiliyorlardı * inandı * kullanım geçerliydi. – JaredPar