2

I am currently converting vb and vb.net to c# but have an issue. I would strongly like not to use the visualbasic dlls in the converted code and have been doing this fine so far.

But this code

Dim x as Double    'this was error saying it was integer
x = Val("1 23 45 x 6")  ''#x is  12345
x = Val("1..23")    ''#x is 1.23
x = Val("1 1,,,,,2,2..3") ''#x is 1122.3

Does not work the same as vb6 even with using "Val" from the visualbasic.conversion.dll Is there anyone that has solved this to work the same? A c# solution would be best.

djv
  • 14,260
  • 7
  • 47
  • 68
Aditya Om
  • 186
  • 1
  • 3
  • 8
  • 15
    How can x be 1.23 when it's declared to be an integer? – Jon Skeet Dec 01 '10 at 15:21
  • 2
    It's one of those fractional integers, those are all the fad now... – SWeko Dec 01 '10 at 15:25
  • 3
    Personally I think that function is insane. If a German (non programmer) enters "1,23" he won't be happy with 123 as a result instead of 1.23 – CodesInChaos Dec 01 '10 at 15:35
  • @Code - on a german system, it's smart enough to know that , rather than . is the decimal point. – Joel Coehoorn Dec 01 '10 at 15:39
  • @Joel: According to the documentation it isn't smart enough: *"The `Val` function recognizes only the period (.) as a valid decimal separator."* http://msdn.microsoft.com/en-us/library/k7beh1x9.aspx – LukeH Dec 01 '10 at 15:41
  • @Joel even if it were that smart it would create evil traps. For example I have a German windows, but as a programmer I'm trained to use `.`, so it would silently fail for me. IMO it's better to think about what input values you expect and show an error on anything unexpected. – CodesInChaos Dec 01 '10 at 15:43
  • sorry, not integer - in simplifing the code I made a typeo – Aditya Om Dec 01 '10 at 15:48

6 Answers6

5

None of the above seemed to satisfy my needs, so I wrote the following:

public static Double Val(string value)
{
    String result = String.Empty;
    foreach (char c in value)
    {
        if (Char.IsNumber(c) || (c.Equals('.') && result.Count(x => x.Equals('.')) == 0))
            result += c;
        else if (!c.Equals(' '))
            return String.IsNullOrEmpty(result) ? 0 : Convert.ToDouble(result);
    }
    return String.IsNullOrEmpty(result) ? 0 : Convert.ToDouble(result);
}

Results of the test data:

"0 1 5.2123 123.123. 1 a" returns 15.21233123

" 1 5.2123 123a" returns 15.21233123

"a1 5.2123 123.123. 1 a" returns 0

"" returns 0

Reuben Mallaby
  • 5,670
  • 4
  • 49
  • 43
ericosg
  • 4,757
  • 4
  • 32
  • 54
5

I know nothing of this VisualBasic.Conversion.dll (and neither does google), but the Microsoft.VisualBasic namespace (in Microsoft.VisualBasic.dll) is part of the core framework and perfectly fine and acceptable to use from C#. There are other nice gems in there as well (ie TextFieldParser), but this should have the exact Val() implementation you need.

If this is the library you've already tried and it doesn't seem right, then I'd go take another look at the unit tests on it.

Outside of this, the accepted ways in C# for converting strings to integers are int.Parse(), int.TryParse(), and Convert.ToInt32(). But, like it or not, the Val() function from the Microsoft.VisualBasic.dll library is the closest match you're going to find for your code's existing behavior.

Joel Coehoorn
  • 380,066
  • 110
  • 546
  • 781
  • I understand and thanks - I was wishing for Val() to match completely the vb6 Val, but perhaps close will be good. – Aditya Om Dec 01 '10 at 15:50
  • 1
    +1 Don't let prejudice harm your productivity. See also discussion [here](http://stackoverflow.com/questions/226517/is-the-microsoft-visualbasic-namespace-true-net-code) – MarkJ Dec 01 '10 at 17:43
1

There is no exact equivalent of vb6 val function in C#. But this function can be used by using Microsoft.VisualBasic namespace in C#.

To use val() function in C# add Microsoft.VisualBasic namespace and use following code:

Conversion.Val("09sdf");
ArunPratap
  • 4,430
  • 7
  • 26
  • 42
1

Check out this site: http://www.dreamincode.net/forums/topic/36064-val-replacement/ where others give an example how to implement your own Val() function.

Peter
  • 13,277
  • 10
  • 69
  • 115
  • *"I would strongly like not to use the visualbasic dlls in the converted code..."* – LukeH Dec 01 '10 at 15:24
  • Sorry about that. Added a link to another site where they suggest implementing your own Val() function. – Peter Dec 01 '10 at 15:26
  • 2
    @Peter: For what it's worth, I think that using the existing `Val` is the best option given that it provides the exact functionality that the OP wants. (Not to mention that it's already been tried-and-tested millions of times in millions of situations.) – LukeH Dec 01 '10 at 15:31
  • @LukeH it does not give exact functionality as it does not behave exactly as vb6 val, but it is close that may work. – Aditya Om Dec 01 '10 at 15:53
  • @Aditya You need to ask yourself some questions. What are the real, concrete, benefits of avoiding the existing `Val`, which is a core part of the .Net framework and fully supported by Microsoft? And how much time are you willing to invest to avoid using `Val`? – MarkJ Dec 01 '10 at 17:28
  • 3
    As far as I can see all of the various reimplemntations in that link will work fail with some of the examples in Aditya's question. None of them account for strings containing decimal points (numbers with fractional parts). For pity's sake, just use Microsoft.VisualBasic.dll, and move on to implement some more functionality for the poor old users. – MarkJ Dec 01 '10 at 17:39
  • Val is way more complicated than it seems like it should be. I would not try to implement my own. Just use the VB one if you are converting legacy code. On new code I use tryparse, I don't like val for parsing textboxes as it provides a lot of unexpected surprises for the users. E.G. 6d3 = 6000 And 6.0% throws an exception. – dwidel Feb 22 '11 at 16:44
1

You could use the Convert static class. It's pretty close to Val() but you need to specify the convert to type. It's in the System namespace.

E.g.:

int x = Convert.ToInt32("23");
int y = Convert.ToDouble("23.342");

http://msdn.microsoft.com/en-us/library/system.convert(v=vs.71).aspx

thkala
  • 80,583
  • 22
  • 150
  • 196
Johnny B
  • 21
  • 1
  • 1
    It's not as close a match as you may think because `Val("") = 0` but `Convert.ToDouble("")` throws an exception – Matt Wilko Feb 11 '15 at 17:03
0

From your examples it could look similar to this. But since I don't know the VB val specification it might not work on all strings correctly.

Decimal ParseNumerString(string s)
{
    Decimal value=0;
    Decimal multiplier=1;
    bool decimalPart=false;
    foreach(char c in s)
    {
      if(IsDigit(c))
      {
        int i=ParseDigit(c);
        if(!decimalPart)
        {
          value=value*10+i;
        }
        else
        {
         muliplier/=10;
         value=value+multiplier*i;
        }
      if(c=='.')
        decimapPart=true;
      }
      return value;
}

This is pseudocode you need to implement parse digit and is digit yourself(trivial). I chose Decimal as internal representation because that way I don't get strange rounding errors in the fractional part.

CodesInChaos
  • 103,479
  • 23
  • 206
  • 257