Best vb.net questions in January 2011

vb.net - Interrupt form loop and end form

61 votes

Hey, I have a form that goes through an endless loop and processes data. When I click a button that "closes" the form the form keeps processing even though it is closed. I want the form to completely end and exit out of its loop statement. Then open a new form.

Here is the code I am using to close the form

frmMain.Close()
frmMain.Dispose()

Note: I am not using threads its just a simple vb.net application. I am not closing the main startup form.

The "correct" way of doing this is with background worker threads really. But this will also work without the need of background worker threads.

Declare a variable in the form class.

Private keepLoopAlive As Boolean

Then write your processing loop to be something like:

keepLoopAlive = True

Do While keepLoopAlive 

    (your code that loops here)

    DoEvents

Loop

Then on your Close event do:

keepLoopAlive = False
Me.Close()

This will cause the loop to end first chance it gets, and your form should close.

Please note I've written this code from memory and not in an IDE so there may be typos.

what can C# do that VB.Net can't ?

12 votes

If you recall, ten years ago "C" programming language had some advantages over "VB" and at that time "C" could DO things that "VB" could not.

Is this true when we compare C# vs. VB.Net ? What can C# do that VB.Net can't ?

Depends on what you mean by can't do. For example VB has XML literals but C# doesn't, but of course you can process XML in C#, just in a different way.

Ultimately I would say there is no problem that C# can solve which VB can't, the syntax and approaches are slightly different that's all.

Going forward there is a commitment from Microsoft to release future features for both languages at the same time, i.e. they won't go off developing specific features for just VB or C#. The syntax implementation of features will differ however, in line with their different syntactic flavours.

Why use String.Format?

11 votes

Why would anyone use String.Format in C# and VB .NET as opposed to the concatenation operators (& in VB, and + in C#)?

What is the main difference? Why are everyone so interested in using String.Format? I am very curious.

I can see a number of reasons:

Readability

string s = string.Format("Hey, {0} it is the {1}st day of {2}.  I feel {3}!", _name, _day, _month, _feeling);

vs:

string s = "Hey," + _name + " it is the " + _day + "st day of " + _month + ".  I feel " + feeling + "!";

Format Specifiers (and this includes the fact you can write custom formatters)

string s = string.Format("Invoice number: {0:0000}", _invoiceNum);

vs:

string s = "Invoice Number = " + ("0000" + _invoiceNum).Substr(..... /*can't even be bothered to type it*/)

String Template Persistence

What if I want to store string templates in the database? With string formatting:

_id         _translation
  1         Welcome {0} to {1}.  Today is {2}.
  2         You have {0} products in your basket.
  3         Thank-you for your order.  Your {0} will arrive in {1} working days.

vs:

_id         _translation
  1         Welcome
  2         to
  3         .  Today is
  4         . 
  5         You have
  6         products in your basket.
  7         Someone
  8         just shoot
  9         the developer.

Is Mono's VB.Net support ready for a production site?

9 votes

Previously, I've only used Microsoft-centric solutions, but for an upcoming ASP.Net project I'm considering using Mono and hosting it on a Linux Amazon EC2 instance. Based on the responses to my previous question, this sounds doable. However, I'm most comfortable with VB.Net and I'm wondering how well Mono supports it.

Does anyone have first-hand experience writing ASP.Net applications for Mono using VB.Net? If so, I'd like to know how it went, what kind of compatibility issues you ran into, and if you consider Mono's VB.Net support ready for use on a production site?

I know Mono's C#.Net support is very good, so that's my fall-back plan, but I'd really prefer to use VB.Net.

The VB compiler hasn't been abandoned, it's just a lack of time that is preventing the required work to update to newer VB versions.

Currently vbnc has support for VB 8 (aka Visual Studio 2005), with a few minor features from newer VB versions.

The easiest and safest would be to precompile your site on Windows, in which case you won't have to deal with any potential compiler issues (and you can use the most recent Visual Studio version). If you take this route you shouldn't run into any bugs you wouldn't hit using C# [1]

[1]: You'd be referencing one assembly more: Microsoft.VisualBasic.dll, which could be a source of bugs - but if you adhere to what is considered good programming practice for VB (turn on Option Strict) the chances that you'll hit any significant new bugs is pretty low.

Inconsistency in divide-by-zero behavior between different value types

6 votes

Please consider the following code and comments:

Console.WriteLine(1 / 0); // will not compile, error: Division by constant zero

int i = 0;
Console.WriteLine(1 / i); // compiles, runs, throws: DivideByZeroException

double d = 0;
Console.WriteLine(1 / d); // compiles, runs, results in: Infinity   

I can understand the compiler actively checking for division by zero constant and the DivideByZeroException at runtime but:

Why would using a double in a divide-by-zero return Infinity rather than throwing an exception? Is this by design or is it a bug?

Just for kicks, I did this in VB.NET as well, with "more consistent" results:

dim d as double = 0.0
Console.WriteLine(1 / d) ' compiles, runs, results in: Infinity

dim i as Integer = 0
Console.WriteLine(1 / i) '  compiles, runs, results in: Infinity

Console.WriteLine(1 / 0) ' compiles, runs, results in: Infinity

EDIT:

Based on kekekela's feedback I ran the following which resulted in infinity:

    Console.WriteLine(1 / 
    .0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);

This test seems to corroborate the idea and a literal double of 0.0 is actually a very, very tiny fraction which will result in Infinity...

In a nutshell: the double type defines a value for infinity while the int type doesn't. So in the double case, the result of the calculation is a value that you can actually express in the given type since it's defined. In the int case, there is no value for infinity and thus no way to return an accurate result. Hence the exception.

VB.NET does things a little bit differently; integer division automatically results in a floating point value using the / operator. This is to allow developers to write, e.g., the expression 1 / 2, and have it evaluate to 0.5, which some would consider intuitive. If you want to see behavior consistent with C#, try this:

Console.WriteLine(1 \ 0)

Note the use of the integer division operator (\, not /) above. I believe you'll get an exception (or a compile error--not sure which).

Similarly, try this:

Dim x As Object = 1 / 0
Console.WriteLine(x.GetType())

The above code will output System.Double.

As for the point about imprecision, here's another way of looking at it. It isn't that the double type has no value for exactly zero (it does); rather, the double type is not meant to provide mathematically exact results in the first place. (Certain values can be represented exactly, yes. But calculations give no promise of accuracy.) After all, the value of the mathematical expression 1 / 0 is not defined (last I checked). But 1 / x approaches infinity as x approaches zero. So from this perspective if we cannot represent most fractions n / m exactly anyway, it makes sense to treat the x / 0 case as approximate and give the value it approaches--again, infinity is defined, at least.

Faster way to convert from a String to generic type T when T is a valuetype?

6 votes

Does anyone know of a fast way in VB to go from a string to a generic type T constrained to a valuetype (Of T as Structure), when I know that T will always be some number type?

This is too slow for my taste:

Return DirectCast(Convert.ChangeType(myStr, GetType(T)), T)

But it seems to be the only sane method of getting from a String --> T. I've tried using Reflector to see how Convert.ChangeType works, and while I can convert from the String to a given number type via a hacked-up version of that code, I have no idea how to jam that type back into T so it can be returned.

I'll add that part of the speed penalty I'm seeing (in a timing loop) is because the return value is getting assigned to a Nullable(Of T) value. If I strongly-type my class for a specific number type (i.e., UInt16), then I can vastly increase the performance, but then the class would need to be duplicated for each numeric type that I use.

It'd almost be nice if there was converter to/from T while working on it in a generic method/class. Maybe there is and I'm oblivious to its existence?


Conclusion:
Testing the three provided implementations below and my original DirectCast/ChangeType form, @peenut's approach of using a prepared delegate to fetch the Parse method from a basic type works. No error checking is done, however, so implementors need to remember to only use this with valuetypes that have a Parse method available. Or extend the below to do error checking.

All runs were done on a 32bit system running Windows Server 2003 R2 with 4GB of RAM. Each "run" is 1,000,000 executions (ops) of the method to be tested, timed with StopWatch and reported back in milliseconds.

Original DirectCast(Convert.ChangeType(myStr, GetType(T)), T):

1000000 ops: 597ms
Average of 1000000 ops over 10 runs: 472ms
Average of 1000000 ops over 10 runs: 458ms
Average of 1000000 ops over 10 runs: 453ms
Average of 1000000 ops over 10 runs: 466ms
Average of 1000000 ops over 10 runs: 462ms


Using System.Reflection and calling InvokeMethod to get at the Parse method:

1000000 ops: 12213ms
Average of 1000000 ops over 10 runs: 11468ms
Average of 1000000 ops over 10 runs: 11509ms
Average of 1000000 ops over 10 runs: 11524ms
Average of 1000000 ops over 10 runs: 11509ms
Average of 1000000 ops over 10 runs: 11490ms


Konrad's approach to generate IL code to access the Parse method and store the call into a delegate:

1000000 ops: 352ms
Average of 1000000 ops over 10 runs: 316ms
Average of 1000000 ops over 10 runs: 315ms
Average of 1000000 ops over 10 runs: 314ms
Average of 1000000 ops over 10 runs: 314ms
Average of 1000000 ops over 10 runs: 314ms


peenut's approach of using a delegate to access the Parse method directly:

1000000 ops: 272ms
Average of 1000000 ops over 10 runs: 272ms
Average of 1000000 ops over 10 runs: 275ms
Average of 1000000 ops over 10 runs: 274ms
Average of 1000000 ops over 10 runs: 272ms
Average of 1000000 ops over 10 runs: 273ms



Comparatively, peenut's approach is almost 200ms faster when executed 1,000,000 times in a tight loop, so his approach wins out. Although, Konrad's wasn't far behind and is itself a fascinating study of things like ILGenerator. Props to all who contributed!

Yes, I know about faster solution :-)

Faster solution is to use prepared delegate for given (generic) Type T. If you are only interested in String->(built-in numeric type), you can simply get Parse method with one argument (String).

Program to test speed of possibilities. Note that only first two methods are generic, 3rd and 4th methods are for comparison only.

Imports System.Reflection

Module Module1

    Public Class Parser(Of T As Structure)

        Delegate Function ParserFunction(ByVal value As String) As T

        Public Shared ReadOnly Parse2 As ParserFunction = GetFunction()

        Private Shared Function GetFunction() As ParserFunction
            Dim t As Type = GetType(T)
            Dim m As MethodInfo = t.GetMethod("Parse", New Type() {GetType(String)})
            Dim d As ParserFunction = DirectCast( _
               ParserFunction.CreateDelegate(GetType(ParserFunction), m),  _
               ParserFunction)
            Return d
        End Function


        Public Shared Function Parse1(ByVal value As String) As T
            Return DirectCast(Convert.ChangeType(value, GetType(T)), T)
        End Function
    End Class

    Sub Main()

        Dim w As New Stopwatch()

        'test data:
        Dim arrStr() As String = New String(12345678 - 1) {}
        Dim r As New Random
        For i As Integer = 0 To arrStr.Length - 1
            arrStr(i) = r.Next().ToString()
        Next
        Dim arrInt1() As Integer = New Integer(arrStr.Length - 1) {}
        Dim arrInt2() As Integer = New Integer(arrStr.Length - 1) {}


        Console.WriteLine("1. method - Convert.ChangeType:")
        w.Reset()
        w.Start()
        For i As Integer = 0 To arrStr.Length - 1
            arrInt1(i) = Parser(Of Integer).Parse1(arrStr(i))
        Next
        w.Stop()
        Console.WriteLine(w.Elapsed)
        Console.WriteLine()

        Console.WriteLine("2. method - prepared delegate:")
        w.Reset()
        w.Start()
        For i As Integer = 0 To arrStr.Length - 1
            arrInt2(i) = Parser(Of Integer).Parse2(arrStr(i))
        Next
        w.Stop()
        Console.WriteLine(w.Elapsed)
        Console.WriteLine()

        Console.WriteLine("3. method - Integer.Parse:")
        w.Reset()
        w.Start()
        For i As Integer = 0 To arrStr.Length - 1
            arrInt2(i) = Integer.Parse(arrStr(i))
        Next
        w.Stop()
        Console.WriteLine(w.Elapsed)
        Console.WriteLine()

        Console.WriteLine("4. method - CType:")
        w.Reset()
        w.Start()
        For i As Integer = 0 To arrStr.Length - 1
            arrInt2(i) = CType(arrStr(i), Integer)
        Next
        w.Stop()
        Console.WriteLine(w.Elapsed)
        Console.WriteLine()
    End Sub
End Module

You can change number of tested elements, if you want. I used 12345678 random integers. Program outputs for me:

1. method - Convert.ChangeType:
00:00:03.5176071

2. method - prepared delegate:
00:00:02.9348792

3. method - Integer.Parse:
00:00:02.8427987

4. method - CType:
00:00:05.0542241

Ratio of times: 3.5176071 / 2.9348792 = 1.20

Understanding floating point problems

6 votes

Could someone here please help me understand how to determine when floating point limitations will cause errors in your calculations. For example the following code.

CalculateTotalTax = function (TaxRate, TaxFreePrice) {
     return ((parseFloat(TaxFreePrice) / 100) * parseFloat(TaxRate)).toFixed(4);
};

I have been unable to input any two values that have caused for me an incorrect result for this method. If I remove the toFixed(4) I can infact see where the calculations start to lose accuracy (somewhere around the 6th decimal place). Having said that though, my understanding of floats is that even small numbers can sometimes fail to be represented or have I misunderstood and can 4 decimal places (for example) always be represented accurately.

MSDN explains floats as such...

This means they cannot hold an exact representation of any quantity that is not a binary fraction (of the form k / (2 ^ n) where k and n are integers)

Now I assume this applies to all floats (inlcuding those used in javascript).

Fundamentally my question boils down to this. How can one determine if any specific method will be vulnerable to errors in floating point operations, at what precision will those errors materialize and what inputs will be required to produce those errors?

Hopefully what I am asking makes sense.

Start by reading What Every Computer Scientist Should Know About Floating Point: http://docs.sun.com/source/806-3568/ncg_goldberg.html

Short answer: double precision floats (which are the default in JavaScript) have about 16 decimal digits of precision. Rounding can vary from platform to platform. If it is absolutely essential that you get the consistently right answer, you should do rational arithmetic yourself (this doesn't need to be hard - for currency, maybe you can just multiply by 100 to store the number of cents as an integer).

But if it suffices to get the answer with a high degree of precision, floats should be good enough, especially double precision.

Using left double quotation marks in strings in VB

6 votes

In following code, the usage of the string "“" (i.e. a left double quotation mark inside a string) results in a compile error in VB.NET:

StringVar = Replace(StringVar, "“", "“")

What’s going on here?

It seems as if you want to replace curly quotes with their HTML code equivalent.

On the first glance, your code is absolutely correct. The problem is that VB allows curly quotes in place of regular quotes in code (because Unicode is great, right?). That is, the following codes are all equivalent:

Dim str = "hello"
Dim str = “hello”
Dim str = "hello“

Now, if you want to use a quotation mark inside a string, VB doesn’t know whether the quotation mark is supposed to end the string or not. In C#, this would be fixed by escaping the quotation mark, i.e. in place of """ you’d write "\"". In VB, the same is done by doubling the quotation mark, i.e. """".

Back to your curly quote. The same as for straight quotes applies according to the VB language specification (¶1.6.4). So to write a curly quote in code, try the following:

StringVar = Replace(StringVar, "““", "“")

Unfortunately, I cannot try this code now and it’s altogether possible that the IDE simply replaces this by straight quotes. If that’s the case, an alternative is to use Chr or ChrW with the character code of the “left double quotation mark”:

StringVar = Replace(StringVar, ChrW(&H201C), "“")

Or, for symmetry, written in decimal (but I prefer hexadecimal for character codes):

StringVar = Replace(StringVar, ChrW(8220), "“")

Something else: the Replace function will probably soon be deprecated and doesn’t work everywhere (e.g. Windows Phone 7). Instead, use the Replace method of the String class:

StringVar = StringVar.Replace(, ChrW(8220), "“")

Acceleration/Deceleration Ratio equivalent with KeyFrame

6 votes

Is there a formula to translate AccelerationRatio or DecelerationRatio to Bezier control points for use in a KeySpline in a SplineDoubleKeyFrame? For example, an "Ease Out" may be DecelerationRatio=0.5, but this doesn't seem equivalent to KeySpline="0.0,0.0 0.5,1.0" or KeySpline="0.5,0 1,0.5".

Would this involve multiple SplineDoubleKeyFrame to achieve DecelerationRatio=0.5? Or is their a particular formula that makes them equivalent in a single frame?

Or is this not to be achieved via a SplineDoubleKeyFrame but a EasingDoubleKeyFrame instead (if so, what is the EasingFunction/EasingMode/Other Attributes)?

Essentially, I'm trying to achieve <DoubleAnimation Storyboard.TargetName="deceleratedRectangle" Storyboard.TargetProperty="(Rectangle.Width)" DecelerationRatio="0.5" Duration="0:0:10" From="20" To="400" /> with KeyFrames as there will be multiple frames that target the same property path and accelerate/decelerate it.


UPDATE: According to the Microsoft WPF-Silverlight Comparison Whitepaper.pdf on page 7:

The linear interpolation can be modified somewhat by adding AccelerationRatio and DecelerationRatio properties to the animation. These attributes essentially create three linear interpolations for the entire animation in order to modify the starting and stopping speeds. For example, a designer would use these attributes to have an object gradually pick up speed or stop suddenly. Unfortunately, Silverlight does not implement these two attributes, but the effect can be duplicated using keyframe animations with linear interpolation.

So I guess this means it can be done with just 3 key frames, but what the formula is I have no idea.


SOLUTION: For others that may come along that need this, posting the ECMAScript solution crafted by Peter Taylor:

<html>
    <head>
        <title>Acceleration or deceleration with Bezier splines</title>
        <script type="text/javascript"><!--
            function calcBezier() {
                var res = new Array();
                var y0 = +document.getElementById("y0").value;
                var y1 = +document.getElementById("y1").value;
                var t0 = +document.getElementById("t0").value;
                var t1 = +document.getElementById("t1").value;
                var ra = +document.getElementById("ra").value;
                var rd = +document.getElementById("rd").value;

                var ta = t0 + ra * (t1 - t0);
                if (ra > 0) res.push("ta = " + ta + "<br />");
                var td = t1 - rd * (t1 - t0);
                if (rd > 0) res.push("td = " + td + "<br />");

                var vm = 2 * (y1 - y0) / (t1 + td - ta - t0);
                res.push("vm = " + vm + "<br />");

                var ya = y0 + vm * (ta - t0) / 2
                if (ra > 0) res.push("ya = " + ya + "<br />");
                var yd = y1 - vm * (t1 - td) / 2
                if (rd > 0) res.push("yd = " + yd + "<br />");

                res.push('&lt;DiscreteDoubleKeyFrame KeyTime="'+t0+'" Value="'+y0+'" /&gt;<br />');

                if (ra > 0) {
                    // y - ya = (t - ta) * vm => t = ta + (y - ya) / vm
                    var p1t = ta - (ya - y0) / vm;
                    // Scale for spline params: (t0,y0):(0,0) and (ta,ya):(1,1)
                    p1t = (p1t - t0) / (ta - t0);
                    // Lift to cubic.
                    res.push('&lt;SplineDoubleKeyFrame KeyTime="'+ta+'" Value="'+ya+'" KeySpline="'+((2*p1t)/3)+',0 '+((2*p1t+1)/3)+','+(1/3)+'" /&gt;<br />');
                }

                if (ra + rd < 1) {
                    res.push('&lt;LinearDoubleKeyFrame KeyTime="'+td+'" Value="'+yd+'" /&gt;<br />');
                }

                if (rd > 0) {
                    var q1y = 1;
                    var q1t = td + (y1 - yd) / vm;
                    q1t = (q1t - td) / (t1 - td);
                    res.push('&lt;SplineDoubleKeyFrame KeyTime="'+t1+'" Value="'+y1+'" KeySpline="'+((2*q1t)/3)+','+(2/3)+' '+((2*q1t+1)/3)+',1" /&gt;<br />');
                }

                document.getElementById("results").innerHTML = res.join("");
            }
        //-->
        </script>
    </head>
    <body>
        <p>Interpolate y from <input id="y0" /> to <input id="y1" />.</p>
        <p>Start time: <input id="t0" />; end time: <input id="t1" />.</p>
        <p>Acceleration ratio: <input id="ra" />; deceleration ratio: <input id="rd" />.</p>
        <p><input type="submit" value="Calculate" onclick="calcBezier();" /></p>
        <p id="results">&nbsp;</p>
    </body>
</html>

General solution

Update: using the geometric interpretation of calculus as the area under a line, I've worked out how to simplify the derivation a lot.

So we're interpolating from y0 at time t0 to y1 at time t1 with acceleration ratio ra and deceleration ratio rd. The definition of the ratios give us the time at which we stop accelerating, ta = t0 + ra * (t1 - t0), and at which we start decelerating, td = t1 - rd * (t1 - t0).

I understand the documentation you quote to mean that it's constant acceleration from t0 to ta, and constant deceleration from td to t1. We'll take the maximum speed reached to be vm.

 Speed
   |        _____________________________________
vm +       /|                                   |\
   |      /                                       \
   |     /  |                                   |  \
   |    /                                           \
   |   /    |                                   |    \
   |  /                                               \
   | /      |                                   |      \
   |/                                                   \
   +--------+-----------------------------------+--------+---- Time
   t0       ta                                  td       t1

Then the area of the parallelogram is the distance travelled from t0 to t1, which is y1 - y0. The area of a parallelogram is the product of the height with the average of the parallel sides. So

y1 - y0 = vm * ((t1 - t0) + (td - ta)) / 2

or

vm = 2 * (y1 - y0) / (t1 + td - ta - t0)

Using just the area of the triangles at the end, we can find how far we've travelled when we stop accelerating, ya = y(ta), and when we start decelerating, yd = y(td).

ya = y0 + vm * (ta - t0) / 2

yd = y1 - vm * (t1 - td) / 2

Finally we produce a quadratic Bezier for [t0, ta], a straight line (ta, ya) - (td, yd), and a quadratic Bezier for [td, t1].

For the first Bezier, we have the obvious control points P0 = (t0, y0) and P2 = (ta, ya). To find P1 we use the property that P0-P1 is tangent to the curve and P1-P2 is tangent to the curve (in general, for an order-n curve P0-P1 and P(n-1)-Pn are tangent). So P1 is at the intersection of y=y0 and the straight line of the middle segment. Similarly for the other Bezier: Q0 = (td, yd), Q2 = (t1, y1), and Q1 is at the intersection of y=y1 and the straight line of the middle segment.


Worked example:

No fade in (acceleration ratio = 0), deceleration ratio = 0.5, t0 = 0, t1 = 10 (seconds), y0 = 20, y1 = 400. I think this corresponds to your specific question.

ta = 0 (and we can omit the first quadratic Bezier); td = t1 - 0.5 * (t1 - t0) = 5.

vm = 2 * (y1 - y0) / (t1 + td - ta - t0) = 2 * (400 - 20) / (10 + 5 - 0 - 0) = 2 * 380 / 15 = 152 / 3 ~= 50.67.

Ignore ya because we're skipping that Bezier.

yd = y1 - vm * (t1 - td) / 2 = 400 - 152/3 * (10-5)/2 = 400 - 380/3 = 820/3 ~= 273.3

So the straight line goes from (t=0, y=20) to (t=5, y=273.3). The deceleration Bezier has Q0 = (5, 273.3), Q2 = (10, 400).

To find Q1 we extend the straight line to y=400. The line has equation y - 20 = (t - 0) * (273.3 - 20) / (5 - 0), so t = 5 * (400 - 20) / (273.3 - 20) = 7.5.

So we have straight line (0,20)-(5,273.3) and a quadratic Bezier with control points (5,273.3), (7.5,400) and (10,400).

Translating this into your keyframe

However, there's a slight hitch, which is that Microsoft hasn't deigned to give us quadratic splines. We have to lift the quadratic Q0, Q1, Q2, to the cubic Q0, (Q0 + 2 Q1) /3, (2 Q1 + Q2) / 3, Q2.

We also have to rescale the control points to 0-1. If we apply that rescaling first, we have (0,0)-(0.5,1)-(1,1). So the cubic is (0,0)-(0.333,0.667)-(0.667,1)-(1,1).

I know splines, but not WPF. I think that the following will do what you want:

<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="20" />
<LinearDoubleKeyFrame KeyTime="0:0:5" Value="273.333" />
<SplineDoubleKeyFrame KeyTime="0:0:10" Value="400" KeySpline="0.333,0.667,0.667,1"/>

Universality of the transformation

Rescaling the first Bezier, we map (t0, y0) to (0, 0) and (ta, ya) to (1, 1). Therefore we map (P1.t, P1.y) to ((P1.t - t0) / (ta - t0), (P1.y - y0) / (ya - y0)). But P1 is at the intersection of y = y0 with the straight line of gradient vm through (ta, ya), which therefore has equation (y - ya) = (t - ta) * vm. So P1.y = y0 and P1.t = ta + (y0 - ya) / vm = ta - (ya - y0) / vm. Plugging in our identity ya = y0 + vm * (ta - t0) / 2, we get P1.t = ta - (vm * (ta - t0) / 2) / vm = ta - (ta - t0) / 2 = (ta + t0) / 2.

So rescaling we map P1 to (0.5, 0). Therefore when we lift it to a cubic Bezier, the intermediate control points are always at (1/3, 0) and (2/3, 1/3).

Similarly the deceleration spline always has its scaled intermediate points at (1/3, 2/3) and (2/3, 1).

Are nested Try/Catch blocks a bad idea?

6 votes

Let's say we have a structure like so:

Try
  ' Outer try code, that can fail with more generic conditions, 
  ' that I know less about and might not be able to handle

  Try
    ' Inner try code, that can fail with more specific conditions,
    ' that I probably know more about, and are likely to handle appropriately
  Catch innerEx as Exception
    ' Handle the inner exception
  End Try

Catch outerEx as Exception
  ' Handle outer exception
End Try

I have seen some opinions that nesting Try blocks like this is discouraged, but I could not find any specific reasons.

Is this bad code? If so, why?

There are certain circumstances where it's good - one try/catch for the whole method and another inside a loop as you want to handle the exception and continue processing the rest of a collection/list

Really the only reason to do it is if you want to skip the bit that errored and carry on - perhaps when opening multiple files, etc...

That said, exceptions should be that - exceptions. A program should handle them but try to avoid them at all costs (they're compuationally very expensive)

One other technique which can be useful is catching specific exception types...

Try
    'Some code to read from a file

Catch ex as IOException
    'Handle file access issues (possibly silently depending on usage)
Catch ex as Exception
    'Handle all other exceptions
End Try

as pointed out by gooch in the comments below, we also use nested try/catches in our error handling routines...

    Try
        Try
            'Log to database
        Catch ex As Exception
            'Do nothing
        End Try

        Try
            'Log to file
        Catch ex As Exception
            'Do nothing
        End Try
    Catch ex As Exception
        'Give up and go home
    End Try

Avoid reloading all XML data for each repeater - vb.net

6 votes

I am trying to place a repeater within a repeater using xml data. I have it working exactly as I want, but the method I have used reloads the data for each repeater. I think I need to cast as an XmlNode but I'll be honest - I have no idea where to start.

Here is my code - I'd like to keep everything in the code behind if possible.

<script runat="server">

Public doc As New XmlDocument()

Public Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs)

    If Not Page.IsPostBack then

        doc.Load(Server.MapPath("~/myxml/bookstore.xml"))

        Dim nodes As XmlNodeList = doc.SelectNodes("Bookings/Booking[@CLIENT_NO='SA33762']")
        rpMyRepeater.DataSource = nodes
        rpMyRepeater.DataBind()

    End If

End Sub

   Protected Sub itemDB(ByVal s As Object, ByVal e As RepeaterItemEventArgs)
      If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then

         Dim rpt As Repeater = CType(e.Item.FindControl("books"), Repeater)

         If Not (rpt Is Nothing) Then

            doc.Load(Server.MapPath("~/myxml/bookstore.xml"))

            Dim nodes2 As XmlNodeList = doc.SelectNodes("Bookings/Booking[@CLIENT_NO='SA33762']/Products/Book")

            rpt.DataSource = nodes2
            rpt.DataBind()

         End If

      End If
   End Sub

</script>

Any ideas?

Am I missing something here?

Can't you simply comment/remove your doc.Load(Server.MapPath("~/myxml/bookstore.xml")) out within your itemDB Sub? Since you defined doc "globally" and already loaded it on page load? (by doing that you will already avoid reloading the xml)

That said, I do agree with Caspar that you should rather use the XmlDatasource (especially for its caching abilities), you don't have to use the XmlDatasource within your markup - you can always define it within your code-behind as well - Since you're concerned about people seeing your (asp.net server-side based) markup for some reason...

e.g.

Public Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.Load

    If Not Page.IsPostBack Then
        Dim source As New XmlDataSource()
        source.DataFile = "~/myxml/bookstore.xml"
        source.XPath = "Bookings/Booking[@CLIENT_NO='SA33762']"
        rpMyRepeater.DataSource = source
        rpMyRepeater.DataBind()
    End If

End Sub

Markup: (Nice thing you'll notice here, is that we bind the second repeater using the source from the first repeater)

<asp:Repeater ID="rpMyRepeater" runat="server">
    <ItemTemplate>
        <%#XPath("//Booking/NAME/text()")%>
        <asp:Repeater runat="server" ID='books' DataSource='<%#XPathSelect("//Booking/Products/Book") %>'>
            <HeaderTemplate>
                <h2>
                    Books</h2>
            </HeaderTemplate>
            <ItemTemplate>
                <p>
                    Title:
                    <%#XPath("TITLE/text()")%></p>
                <p>
                    <%#XPath("BOOKCODE/text()")%></p>
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>

XML

<?xml version="1.0" encoding="utf-8" ?>
<Bookings>
  <Booking CLIENT_NO="SA33762">
    <NAME>Mr Pf_Test_15033</NAME>
    <Products>
      <Book>
        <TITLE>My Book</TITLE>
        <BOOKCODE>12345</BOOKCODE>
      </Book>
      <Book>
        <TITLE>My Book2</TITLE>
        <BOOKCODE>123456</BOOKCODE>
      </Book>
    </Products>
  </Booking>
</Bookings>

The implementation using the ListView control (one of my favorite asp.net control) will look something like this: (If there's no books available, it will display the markup within the EmptyDataTemplate)

<asp:Repeater ID="rpMyRepeater" runat="server">
    <ItemTemplate>
        <%#XPath("//Booking/NAME/text()")%>
        <asp:ListView runat="server" ID="books" ItemPlaceholderID="phItems" DataSource='<%#XPathSelect("//Booking/Products/Book") %>'>
            <LayoutTemplate>
                <h2>
                    Books</h2>
                <asp:PlaceHolder runat="server" ID="phItems"></asp:PlaceHolder>
            </LayoutTemplate>
            <ItemTemplate>
                <p>
                    Title:
                    <%#XPath("TITLE/text()")%></p>
                <p>
                    <%#XPath("BOOKCODE/text()")%></p>
            </ItemTemplate>
            <EmptyDataTemplate>
                <p>
                    Sorry no books available</p>
            </EmptyDataTemplate>
        </asp:ListView>
    </ItemTemplate>
</asp:Repeater>

VB.NET 'If' statement with 'Or' conditional has both sides evaluated?

5 votes

Hi there,

Quick question, of which the quickest and easiest answer may well be to rearrange related code, but let's see...

So I have an If statement (a piece of code which is a part of a full working solution written in C#) rewritten using VB.NET. I am aware the VB.NET IIf(a, b, c) method evaluates both b and a regardless of the trueness of the first evaluation, but this seems to be the case in my standard construct, too:

If (example Is Nothing Or example.Item IsNot compare.Item) Then
    'Proceed
End If

Or, rather, more appropriately:

If (example Is Nothing Or Not example.Item = compare.Item) Then
    'Proceed
End If

Here, if example is Nothing (null) then I still get an NullReferenceException - is this my fault, or is it something I just have to endure at the whim of VB.NET?

It's your "fault" in that that's how Or is defined, so it's the behaviour you should expect:

In a Boolean comparison, the Or operator always evaluates both expressions, which could include making procedure calls. The OrElse Operator (Visual Basic) performs short-circuiting, which means that if expression1 is True, then expression2 is not evaluated.

But you don't have to endure it. You can use OrElse to get short-circuiting behaviour.

So you probably want:

If (example Is Nothing OrElse Not example.Item = compare.Item) Then
    'Proceed
End If

I can't say it reads terribly nicely, but it should work...

What is the equivalent of C#'s `default` in VB.Net?

5 votes

I'm normally at home in C#, and I'm looking at a performance issue in some VB.Net code -- I want to be able to compare something to the default value for a type (kind like C#'s default keyword).

public class GenericThing<T1, T2>
{    
    public T1 Foo( T2 id )
    {
        if( key != default(T2) ) // There doesn't appear to be an equivalent in VB.Net for this?
        {
            // ...
        }
    }
}

I was led to believe that Nothing was semantically the same, yet if I do:

Public Class GenericThing(Of T1, T2)
    Public Function Foo( id As T2 ) As T1
        If id IsNot Nothing Then
            ' ...
        End If
    End Function
End Class

Then when T2 is Integer, and the value of id is 0, the condition still passes, and the body of the if is evaluated. However if I do:

    Public Function Bar( id As Integer ) As T1
        If id <> Nothing Then
            ' ...
        End If
    End Function

Then the condition is not met, and the body is not evaluated...

This is not a complete solution, as your original C# code doesn't compile. You can use Nothing via a local variable:

Public Class GenericThing(Of T)
    Public Sub Foo(id As T)
        Dim defaultValue As T = Nothing
        If id <> defaultValue Then
            Console.WriteLine("Not default")
        Else
            Console.WriteLine("Default")
        End If
    End Function
End Class

That doesn't compile, in the same way that the C# version doesn't compile - you can't compare values of unconstrained type parameters like that.

You can use EqualityComparer(Of T) though - and then you don't even need the local variable:

If Not EqualityComparer(Of T).Default.Equals(id, Nothing) Then

How does one make a horizontal listbox in .NET

5 votes

I am working on porting a VB6 application to .NET and one of the desired UI elements is a horizontal listbox. I can't seem to figure out how to replicate this in .NET.

  1. Can this be done with basic winforms?

  2. How would you replicate this?

Sample:
alt text

The VB6 code that will replicate the above image:

Private Sub Form_Load()
    lst_horizontal(1).FontSize = 6
    Dim iMaxChoices As Integer
    iMaxChoices = 10
    For i = 1 To iMaxChoices
        lst_horizontal(1).AddItem (" " + CStr(i))
    Next i
End Sub

Private Sub lst_horizontal_Click(Index As Integer)
    Dim iMaxChoices As Integer
    iMaxChoices = 10

    For i = 0 To iMaxChoices - 1

        If lst_horizontal(1).Selected(i) Then
            Debug.Print ("Item " + CStr(i + 1) + " selected")
        End If

    Next i

Weasel words: I can figure out how to replicate this in Silverlight/XAML, but this app can't be done in that fashion.

This is supported in Winforms as well. Set the MultiColumn property to True, the ColumnWidth property to, say, 15.

Nested class Access methods for Properties in .NET

4 votes

Hi, I am trying to figure out the best approach for setting and getting properties in a nested class I am creating.

I have a class, Car which has a nested class ControlPanel and want to make the properties of the Control Panel only accessible to the Car and Control Panel class.

(ie: not within the assembly or namespace and not within the application the class library will be going to be used)... I have changed the class access properties to friend, protected friend, private, public, but any combination is not matching my expected results.

I want to change the properties in the Drive() Sub of a class as shown below.

Any thoughts?

 Public Class Car

    Dim cp As New ControlPanel

    Public Class ControlPanel
      Private _Speedometer As Integer = 0
      Private _Odometer As Integer = 0

      Public Property Speedometer() As Integer
        Get
            Return _Speedometer
        End Get
        Protected Set(ByVal value As Integer)
            _Speedometer = value
        End Set
      End Property

      Public Property Odometer() As Integer
        Get
            Return _Odometer
        End Get
        Protected Set(ByVal value As Integer)
            _Odometer = value
        End Set
     End Property

    End Class

   Public Sub Drive()

        cp.Odometer = 76323
        co.Speedometer = 86

   End Sub

End Class

You can do it like this:

Public Class Car

  Private Interface IControlPanel
    Property Odometer As Integer
    Property Speedometer As Integer
  End Interface

  Public Class ControlPanel
    Implements IControlPanel
    Public ReadOnly Property Odometer As Integer
      Get
        Return CType(Me, IControlPanel).Odometer
      End Get
    End Property
    Public ReadOnly Property Speedometer As Integer
      Get
        Return CType(Me, IControlPanel).Speedometer
      End Get
    End Property
    Private Property IControlPanel_Odometer As Integer Implements IControlPanel.Odometer
    Private Property IControlPanel_Speedometer As Integer Implements IControlPanel.Speedometer
  End Class

  Dim cp As IControlPanel = New ControlPanel()

  Public Sub Drive()
    cp.Odometer = 76323
    cp.Speedometer = 86 
  End Sub

End Class

It uses a private interface nested in the Car class with privately implemented and aliased members in ControlPanel. This way, only Car can access the interface members.

Converting "myself" from C# to VB.NET

4 votes

I am a C# programmer (hobby), but I want to convert to a VB.NET programmer. I have seen many posts written in both C# and VB.NET, but I need some links which explain from the basics (like void main void) to the most advanced.

Note: Microsoft blogs (until now whatever I read) do not refer to the basic core level knowledge/things.

Aside from books/blogs, a good way to learn the other side of the C#/VB wall is to write some code in C#, compile it, and open the DLL in Reflector and view as VB code. This will allow you to answer your own questions about VB.NET.

For example, suppose you want to see how to do generics in VB.NET. You write a simple library in C#:

void SomeMethod()
{
    List<int> list = new List<int>();
}

Compile this, then open in Reflector, and it will show you:

Sub SomeMethod
    Dim list as List(Of Integer) = New List(Of Integer)
End Sub

or something like that...

If you know how to do it in C#, you can probably teach yourself how to do it in VB.NET this way easier than looking for samples online.