пятница, 15 апреля 2011 г.

Последняя битва Героя

Случилось так, что славный рыцарь сэр Эрроурут Эрроуширский, по обыкновению спасая мирных жителей от ужасных созданий, вступил по геройской нужде своей в мрачные и зловонные земли Заброшенного Капища. Ядовитые испарения и дурные предзнаменования окутывали это черное место. С гниющих ветвей деревьев вместо листьев свисали во множестве полуистлевшие человеческие головы и иные бренные члены. Небо было затянуто непроглядной зеленой мглой, а из таинственных темных углов раздавались скрежет зубовный и прочие малоприятные звуки. Любой из героев давно повернул бы назад, но только не Эрроурут! Без тени страха и сомнения продвигался он вперед к своей цели.

Но вот земля содрогнулась под тяжкой поступью неведомого врага, а воздух наполнился отвратительными звуками и запахами. И через мгновение враг явил себя. Ростом он превосходил высочайшие из деревьев и, весь покрытый непробиваемой броней, был подобен черной горе. Четыре гигантские ноги его сотрясали землю, а множественные руки были вооружены острейшими ядовитыми когтями, подобными мечам и секирам. Из разинутой пасти врага виднелись черные клыки в пять локтей длиной, с которых стекала на землю кислота и щелочь. Гигантским своим хоботом он с легкостью выдирал из земли деревья, валуны и иные предметы, помещая их в свою бездонную глотку, откуда вырывались сполохи пламени и оглушительное рычание. Это был тот, о котором многие боятся даже помыслить, тот, чьим именем пугают непослушных детей: мифический демон древнего мира – Администратор Годвилля.

Отважный Эрроурут вспомнил, что излюбленной пищей демона являются молодые и неопытные герои. С жалостью подумал он о тех бедолагах, кто остался за его спиной, и для кого сегодняшний день мог стать последним. И славный рыцарь понял, что долг его – низвергнуть чудовище. Победить или пасть смертью героя! Крепче сжал он в руке оружие – свой верный боевой вантуз, и громогласно провозглашая боевой клич, отважно ринулся в бой. И так велика была его доблесть, что ужасный Администратор Годвилля, на мгновение дрогнув, попытался поджать свой чудовищный шипастый хвост. Но вот новой безумной злобой вспыхнули все восемь глаз демона, и издавая громовое рычание «СЕР-ВЕР», монстр обрушил свою колоссальную мощь на бесстрашного рыцаря…

Три дня и три ночи длилась великая битва, но силы были не равны. На последнем дыхании славный Эрроурут вонзил свое благородное оружие в чудовищную тушу врага и пал, обессилев от многочисленных ран.

Но милостив и справедлив Всемогущий! Отважный рыцарь ожил, чудесным образом очутившись в Храме, и новые славные подвиги ожидали его. Что же случилось с поверженным чудовищным демоном? Героическая гибель отважного рыцаря не была напрасной – ужасного Администратора Годвилля в тех местах боле никто не видел.

пятница, 23 июля 2010 г.

VB.Net. Сравнение быстродействия операций

Приблизительно оценить время выполнения той или иной операции можно следующим образом:

Dim t As DateTime = Now
'некоторая операция 
Console.WriteLine((Now - t).ToString)

Причем, если операция выполняется быстро, имеет смысл поместить ее в цикл. В качестве примера, оценим разницу в быстродействии вариантов проверки пустой строки. Для пущего интересу, пусть строковая переменная будет пустая и непустая.

Dim s As String = "a"
Dim t As DateTime

Console.WriteLine("s = ""a""")

t = Now
For i = 0 To 99999999
    If s = "" Then s.ToString()
Next
Console.WriteLine("If s = """" Then --> " & (Now - t).ToString)

t = Now
For i = 0 To 99999999
    If s = String.Empty Then s.ToString()
Next
Console.WriteLine("If s = String.Empty Then --> " & (Now - t).ToString)

t = Now
For i = 0 To 99999999
    If s.Length = 0 Then s.ToString()
Next
Console.WriteLine("If s.Length = 0 Then --> " & (Now - t).ToString)

s = ""
Console.WriteLine("s = """"")

t = Now
For i = 0 To 99999999
    If s = "" Then s.ToString()
Next
Console.WriteLine("If s = """" Then --> " & (Now - t).ToString)

t = Now
For i = 0 To 99999999
    If s = String.Empty Then s.ToString()
Next
Console.WriteLine("If s = String.Empty Then --> " & (Now - t).ToString)

t = Now
For i = 0 To 99999999
    If s.Length = 0 Then s.ToString()
Next
Console.WriteLine("If s.Length = 0 Then --> " & (Now - t).ToString)

А вот и результаты испытаний, выведенные в консоль:

s = "a"
If s = "" Then --> 00:00:02.2656250
If s = String.Empty Then --> 00:00:02.3125000
If s.Length = 0 Then --> 00:00:00.4062500
s = ""
If s = "" Then --> 00:00:00.7968750
If s = String.Empty Then --> 00:00:02.2187500
If s.Length = 0 Then --> 00:00:00.5000000


Как видим, в любом случае, целесообразнее обращаться к свойству Length. 

четверг, 22 июля 2010 г.

VB.Net. Пустая строка

И еще, к слову. Возможно, кто-то использует такую проверку пустой строки:

If s = "" Then...
или If s = String.Empty Then...

Так проверять не рекомендуется (не рационально). Лучше использовать свойство Length объектов типа String, т.е. делать так:

If s.Length = 0 Then...

Вот так красиво! :)

VB.Net. Удаление элементов коллекции в цикле

Предположим, надо нам удалить из контейнера все элементы управления, свойство Text которых пустое. Как-то раз, не долго думая, я взял и сделал так:

For Each с As Control In Panel1.Controls
    If c.Text.Length = 0 Then Panel1.Controls.Remove(c) 
Next 

Но так делать нельзя! Потому что нельзя изменить коллекцию во время прохода циклом по элементам этой коллекции (а удаляя элемент из коллекции, мы изменяем коллекцию). А вот как можно сделать:
Dim lst As Control() = Panel1.Controls.Cast(Of Control).Where(Function(c) c.Text.Length = 0).ToArray
For Each c In lst
    Panel1.Controls.Remove(c)
    c.Dispose()
Next

Что мы сделали? Сначала поместили все удаляемые элементы коллекции в новый массив lst. Теперь проходим по элементам массива в цикле и делаем, все, что нужно. Можем удалять элемент из исходной коллекции - в массиве он остается, а значит работа цикла не сбивается. Dispose() освобождает ресурсы, занятые объектом. А созданный массив, как локальный объект, прекратит свое существование при выходе из текущей процедуры.

среда, 21 июля 2010 г.

VB.Net. Перетаскивание элемента управления мышью по форме

В данном примере мышью по форме перетаскивается элемент управления Label. Конечно, подобным образом может перетаскиваться и любой другой контрол, и не только по форме. Во время перемещения указателя мыши по элементу управления (при нажатой кнопке мыши) положение элемента управления изменяется на величину смещения указателя относительно исходной позиции контрола. Ну, вобщем, вроде бы, все понятно. :) Остальные комментарии смотрите в коде.


Public Class Form1

    Private isMouseDown As Boolean = False 'признак удерживания кнопки мыши
    Private StartPoint As Point 'начальная позиция элемента управления

    Private Sub Label1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then 'если нажата левая кнопка мыши
            isMouseDown = True
            StartPoint = e.Location 'запоминаем текущую позицию элемента управления
            Label1.Cursor = Cursors.SizeAll 'меняем вид указателя мыши над элементом управления
        End If
    End Sub

    Private Sub Label1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseUp
        isMouseDown = False
        Label1.Cursor = Cursors.Default 'восстанавливаем вид курсора
    End Sub

    Private Sub Label1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseMove
        If isMouseDown Then 'если кнопка мыши удерживается
            'вычисляем новые координаты элемента управления
            Label1.Left += (e.X - StartPoint.X)
            Label1.Top += (e.Y - StartPoint.Y)
        End If
    End Sub

    Private Sub Label1_LocationChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label1.LocationChanged
        'если большая часть элемента управления выходит за границу формы, возвращаем его в центр
        Dim w2 As Integer = Convert.ToInt32(Label1.Width / 2)
        Dim h2 As Integer = Convert.ToInt32(Label1.Height / 2)
        If Label1.Top < -h2 Or Label1.Left < -w2 Or Label1.Top > Me.ClientSize.Height - h2 Or Label1.Left > Me.ClientSize.Width - w2 Then
            Label1.Location = New Point(Convert.ToInt32(Me.ClientSize.Width / 2) - w2, Convert.ToInt32(Me.ClientSize.Height / 2) - h2)
            isMouseDown = False
            Label1.Cursor = Cursors.Default
        End If
    End Sub

End Class

Го вверх!