Odlišnosti verzí   otázka

VB6/VBA

Zdravím vás tu všechny :)

a doufám, že mne s mým dotazem hned nevyženete! Ve VBasicu jsem nikdy neprogramoval, ale kdysi se k tomu schylovalo, takže jsem tehdy zakoupil VB5.0. V příručce k němu jsem teď nalezl příklad, který má za úkol projít kolekci Controls na formuláři a do listboxu vypsat názvy jejích všech členů:

For Each Control In Form1.Controls
   List1.AddItem Control.Name
Next Control

Z celkem logických důvodů už nechci používat "pětku", stáhl jsem si proto 2010 express a zjistil, že na ní ani tento, dle mne triviální příklad, nechodí (o změnách příkazů v práci s databázemi ani nemluvě). Od nápovědy a různých hlášek jsem dostával facky zprava zleva, až jsem vytvořil jakýs takýs funkční vzorek, který předkládám vzácnému publiku a ptám se: je to úplně blbě a dělá se to jinak (jak?!), nebo je to takhle správně? Ten můj "přepis" mi přijde složitý, ale zatím se moc neorientuju. Díky za postrčení. Zajisté pak zakoupím i knihu, kterou mi laskavě doporučíte :)

For Each Control In Me.Controls
  With Me.ListBox1.Items
     .Add(Control.name)
  End With
Next

Svatopluk

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Není třeba používat "With" konstrukci, pokud přistupujete pouze k jednomu členu objektu (medotě Add).

For Each control In Me.Controls

Me.ListBox1.Items.Add(control.Name)

Next

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Děkuju, to mi dává smysl - já tu konstrukci With vykradl z příkladu, kde se "něco" přidávalo opakovaně, ovšem explicitně, tak jsem cítil, že je asi nadbytečná, ale nevěděl jsem, jak se jí zbavit :D

Svatopluk

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Akurát, že k tomu členu(ListBox1.Items) pristupuje viackrát, keďže je to v cykle For Each.Navrhol by som vnoriť cyklus For Each do bloku With pôvodného znenia.

With ListBox1.Items
  For Each control In Controls
    .Add(control.Name)
  Next
End With

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Víte vy vůbec, k čemu slouží konstrukce With? Ta se používá, pokud nechcete stále dokola psát Něco.Něco.Něco.Vlastnost! Příklad:

místo

ListBox1.Items.Add("něco")
ListBox1.Items.AddRange(pole)
MsgBox(ListBox1.Items.Count)

stačí napsat

With ListBox1.Items
 .Add("něco")
 .AddRange(pole)
 MsgBox(.Count)
End 

To, že je to v cyklu, neznamená, že máte použít With. K tomu jsou právě ty cykly!!!

nahlásit spamnahlásit spam 1 / 3 odpovědětodpovědět

Podľa môjho vedomia sa používa aj v prípade, že pristupujete k nejakému členu napríklad 10 000x a nechcete, aby to pristúpilo k (väčšinou)vlastnosti, ktorá je za With.Vlastnosť totižto môže používať časovo náročný kód na získanie kolekcie a spustiť časovo náročný kód 10 000x a 1x je rozdiel.

Čo poviete na toto?Je tam síce len 1 000 iterácií, ale rozdiel je dosť značný.

Imports System.IO
Module Module1
    Sub Main()
        Dim sw = Stopwatch.StartNew()
        For x As Integer = 0 To 999
            A.Add(0)
            A.Clear()
        Next
        sw.Stop()
        Console.WriteLine("Without With: {0} ms.", sw.ElapsedMilliseconds)
        sw.Reset()
        sw.Start()
        With A
            A.Add(0)
            A.Clear()
        End With
        Console.WriteLine("With With: {0} ms.", sw.ElapsedMilliseconds)
        sw.Stop()
        Console.ReadLine()
    End Sub
    Private l As New List(Of Integer)
    Public ReadOnly Property A As List(Of Integer)
        Get
            Threading.Thread.Sleep(5)
            Return l
        End Get
    End Property
End Module

'Výstup horeuvedeného programu:
'Without With: 9999 ms.
'With With: 14 ms.
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ospravedlňujem sa, hore uvedený kód bol chybný(14 ms bolo pri jednej jedinej iterácii), ale dôkaz som si aj tak našiel:

Imports System.Windows.Forms
Module Module1
    Sub Main()
        Dim sw = Stopwatch.StartNew()
        Dim frm As New Form
        Dim T As TextBox() = New TextBox(4900) {}
        For x As Integer = 0 To 4900
            T(x) = New TextBox()
        Next
        For x As Integer = 0 To 4900
            frm.Controls.Add(T(x))
        Next
        sw.Stop()
        frm.Controls.Clear()
        Console.WriteLine("Without With: {0} ms.", sw.ElapsedMilliseconds)
        sw.Reset()
        sw.Start()
        With frm.Controls
            For x As Integer = 0 To 4900
                .Add(T(x))
            Next
        End With
        Console.WriteLine("With With: {0} ms.", sw.ElapsedMilliseconds)
        sw.Stop()
        Console.ReadLine()
    End Sub
End Module
'Výstup programu:
'Without With: 5317 ms.
'With With: 4577 ms.
'Rozdiel 740 ms.

'Druhé meranie:
'Without With: 5269 ms.
'With With: 4603 ms.
'Rozdiel 666 ms.

'Tretie meranie:
'Without With: 5435 ms.
'With With: 4654 ms.
'Rozdiel 781 ms.
nahlásit spamnahlásit spam 0 odpovědětodpovědět

:D zase chyba. Máte právo ma teraz pokladať za blbca, ale skúsim to ešte raz.Aj v nasledujúcom kóde je rozdiel patrný.

Imports System.Windows.Forms
Module Module1
    Sub Main()

        Dim frm As New Form
        Dim T As TextBox() = New TextBox(4900) {}
        For x As Integer = 0 To 4900
            T(x) = New TextBox()
        Next
        Dim sw = Stopwatch.StartNew()
        For x As Integer = 0 To 4900
            frm.Controls.Add(T(x))
        Next
        sw.Stop()
        frm.Controls.Clear()
        Console.WriteLine("Without With: {0} ms.", sw.ElapsedMilliseconds)
        sw.Reset()
        sw.Start()
        With frm.Controls
            For x As Integer = 0 To 4900
                .Add(T(x))
            Next
        End With
        Console.WriteLine("With With: {0} ms.", sw.ElapsedMilliseconds)
        sw.Stop()
        Console.ReadLine()
    End Sub
End Module
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak teraz tu mám už niečo rozumnejšie.Pre tých, ktorí sa vedia aspoň trochu zorientovať v IL kóde tu mám ukážku prístupu k návratovej hodnote v cykle bez a s použitím With bloku.

VB.NET:

Sub Main()
        DUMMY_BREAKPOINT("BEGIN WITH WITH BLOCK")
        With GetList()
            DUMMY_BREAKPOINT("BEGIN WITH FOR BLOCK")
            For x As Integer = 0 To 199
                DUMMY_BREAKPOINT("BEGIN WITH INSIDE BLOCK")
                .Add(0)
                DUMMY_BREAKPOINT("END WITH INSIDE BLOCK")
            Next
            DUMMY_BREAKPOINT("END WITH FOR BLOCK")
        End With
        DUMMY_BREAKPOINT("END WITH TEST BLOCK")

        DUMMY_BREAKPOINT("BEGIN WITHOUT FOR BLOCK")
        For x As Integer = 0 To 199
            DUMMY_BREAKPOINT("BEGIN WITHOUT INSIDE")
            GetList().Add(0)
            DUMMY_BREAKPOINT("END WITHOUT INSIDE")
        Next
        DUMMY_BREAKPOINT("END WITHOUT FOR BLOCK")
        Console.ReadLine()
    End Sub

IL:

.method public static void  Main() cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       181 (0xb5)
  .maxstack  2
  .locals init ([0] int32 x,
           [1] int32 V_1,
           [2] class [mscorlib]System.Collections.Generic.List`1<int32> VB$t_ref$L0,
           [3] int32 VB$CG$t_i4$S0)
  IL_0000:  nop
  IL_0001:  ldstr      "BEGIN WITH WITH BLOCK"
  IL_0006:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_000b:  nop
  IL_000c:  call       class [mscorlib]System.Collections.Generic.List`1<int32> TestConsoleApp.Module1::GetList()
  IL_0011:  stloc.2
  IL_0012:  ldstr      "BEGIN WITH FOR BLOCK"
  IL_0017:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_001c:  nop
  IL_001d:  ldc.i4.0
  IL_001e:  stloc.0
  IL_001f:  ldstr      "BEGIN WITH INSIDE BLOCK"
  IL_0024:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_0029:  nop
  IL_002a:  ldloc.2
  IL_002b:  ldc.i4.0
  IL_002c:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_0031:  nop
  IL_0032:  ldstr      "END WITH INSIDE BLOCK"
  IL_0037:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_003c:  nop
  IL_003d:  nop
  IL_003e:  ldloc.0
  IL_003f:  ldc.i4.1
  IL_0040:  add.ovf
  IL_0041:  stloc.0
  IL_0042:  ldloc.0
  IL_0043:  ldc.i4     0xc7
  IL_0048:  stloc.3
  IL_0049:  ldloc.3
  IL_004a:  ble.s      IL_001f
  IL_004c:  ldstr      "END WITH FOR BLOCK"
  IL_0051:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_0056:  nop
  IL_0057:  ldnull
  IL_0058:  stloc.2
  IL_0059:  ldstr      "END WITH TEST BLOCK"
  IL_005e:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_0063:  nop
  IL_0064:  ldstr      "BEGIN WITHOUT FOR BLOCK"
  IL_0069:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_006e:  nop
  IL_006f:  ldc.i4.0
  IL_0070:  stloc.1
  IL_0071:  ldstr      "BEGIN WITHOUT INSIDE"
  IL_0076:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_007b:  nop
  IL_007c:  call       class [mscorlib]System.Collections.Generic.List`1<int32> TestConsoleApp.Module1::GetList()
  IL_0081:  ldc.i4.0
  IL_0082:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_0087:  nop
  IL_0088:  ldstr      "END WITHOUT INSIDE"
  IL_008d:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_0092:  nop
  IL_0093:  nop
  IL_0094:  ldloc.1
  IL_0095:  ldc.i4.1
  IL_0096:  add.ovf
  IL_0097:  stloc.1
  IL_0098:  ldloc.1
  IL_0099:  ldc.i4     0xc7
  IL_009e:  stloc.3
  IL_009f:  ldloc.3
  IL_00a0:  ble.s      IL_0071
  IL_00a2:  ldstr      "END WITHOUT FOR BLOCK"
  IL_00a7:  call       void TestConsoleApp.Module1::DUMMY_BREAKPOINT(string)
  IL_00ac:  nop
  IL_00ad:  call       string [mscorlib]System.Console::ReadLine()
  IL_00b2:  pop
  IL_00b3:  nop
  IL_00b4:  ret
} // end of method Module1::Main

Je celkom jasné, že With blok uloží časť "pred bodkou" do premennej a nebude neustále volať funkciu GetList().

Pozn.: pre lepšiu orientáciu je kód "okomentovaný" volaniami funkcie DUMMY_BREAKPOINT, ako jediný parameter je uvedený text opisujúci miesto v kóde.Tento typ komentáru je zároveň v pôvodnom VB.NET kóde a výslednom IL kóde.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dejte také pozor na pojmenovávání proměnných (proměnné zásadně Camel casing, více v http://www.vbnet.cz/clanek--62-konvence_... ). V některých případech totiž může být Control rozpoznáno jako třída System.Windows.Forms.Control. A když je položka součástí třídy, ve které se nachází aktuálně psaný kód, není třeba uvádět klíčové slovo Me (Controls místo Me.Controls).

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Aha, díky, mně to nadávalo, když jsem tam měl Form1, ale Me to "sneslo", tak už jsem to dál nezkoumal, zdálo se mi, že nějak to určit musím. Asi budu muset opravdu tu příručku k "pětce" odložit. Taky se tu porozhlédnu, co tu máte :), ale taky bych rád něco tištěného. Nejlépe se mi dělá tak, že na jednom monitoru mám prostředí, na druhém otevřu nějaký tutoriál ze kterého můžu příklady kopírovat a taky Help a ještě tutor-knihu, protože se mi nechce pořád koukat na displej, čtečku knih ještě jako náhradu neberu.

Svatopluk

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak na to taky pozor. Z důvodu zpětné kompatibility lze s některými členy třídy Form (Show) pracovat staticky, přestože jsou instanční. Ve VB.NET by se všechno mělo používat instančně. Na plnohodnotný OOP model ve VB.NET si budete muset zvyknout, většinu věcí ze starého VB5/VB6 můžete bez starostí zapomenout.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Zapomenout nebude těžké, byl jsem asi v 1/5 knížky :D.

Teď jsem začal číst místní seriál od Tomáše Hercega, tak jsem zvědavý, kdy se to začne lišit - v té chvíli tomu asi přestanu rozumět :D :D Určitě vaši pomoc brzo využiju až narazím!

Svatopluk

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Proč přejít k VB.NET a to nejlépe k VB.NET 2010 - z hlediska začátečníka.

V 15. dílu seriálu "VB.NET od začátku" ukazuje Tomáš Herceg, jak napsat třídu pro práci se zápisem dat do souboru. Celý příklad používá jako lehoučký úvod do OOP. Tak daleko jsem se ale při učení VB5.0 ani nedostal, měl jsem jen určité povědomí, že tam existují nějaké wizardy, které při práci s vytvářením objektů pomohou, ale že hlavně programátor musí vědět ještě spoustu věcí kolem, jinak si ani neškrtne :).

Takže jsem si tu jeho třídu na(o)psal taky a ono to fungovalo!

Říkám si - Hm, vlastně to ale nic není, místo abych měl ty rutiny v jednom souboru, mám je v jiném a trochu jinak napsané - jó, takhle si moct napsat třídu třeba pro nové tlačítko, to by byla jiná káva! Jenomže na to chlapče nemáš, to nikde neopíšeš a když, tak tomu nebudeš rozumět! Ale co kdyby?!

Pochopitelně google odpověď znal, našel jsem na visualbasic.about.com krásný seriálek An Introduction to Programming a VB.NET Control With Inheritance o tom, jak předělat Checkbox tak, aby místo zaškrtnutí změnil uvnitř barvu.

Je to jednoduché, pochopil jsem to i já, jen druhá, dokonalejší varianta mi dělala trochu potíže, než mi vše došlo.

Jen mi trochu vadilo, že musím umístění komponenty (CheckBoxu) na plochu formuláře nastavovat programem - jó, kdyby byl součástí Tools a já ho tam dostal myškou, jako jiné "normální" komponenty, to by byla jiná káva! (znalci dotnet 2010 se nyní chechtají, jaký jsem to trouba).

Znovu google a znovu objev - After it has been built, you can add it to your toolbox. On the Tools menu, click Customize Toolbox and browse to the .exe created from building your project Takže šup do Tools, Customize..., hm, kde a čím mám hledat nový exáč a co potom s ním? Mimoděk se poprvé pořádně kouknu do Tools a tam hned nahoře je nové záhlaví MůjProjekt Components a v něm newCheckBox... Šel jsem si pro klobouk a smekl jsem. Ty tutoriálky byly napsané před určitým časem a vývojáři zatím nelenili a udělali i ten zbytek práce za mne.

Takže dnes, i když stále ještě nováček ve Visual Basicu, už vím, že jsem udělal dobře, když jsem pětku verzi pustil jako horký brambor a že dokonce i mladší verze dot-net neumí to, co tato poslední - 2010.

Svatopluk

Edit:

Sám jsem také líný něco hledat, tak přidávám odkaz na ten článek:

http://visualbasic.about.com/od/usingvbn...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback