1

I'm following examples in Professional.Test.Driven.Development.with.Csharp I'm converting the code from C# into VB. (this example is the start of chapter 7)

Now having

Public Class ItemType
   Public Overridable Property Id As Integer
End Class

Public Interface IItemTypeRepository
    Function Save(ItemType As ItemType) As Integer
End Interface

Public Class ItemTypeRepository
  Implements IItemTypeRepository

Public Function Save(ItemType As ItemType) As Integer Implements IItemTypeRepository.Save
    Throw New NotImplementedException
End Function
End Class

And in the TestUnit project

<TestFixture>
Public Class Specification
   Inherits SpecBase
End Class

When writing the test in vb.net (should fail) it passes nicely (integer value of 0 = 0)

Public Class when_working_with_the_item_type_repository
   Inherits Specification
End Class

Public Class and_saving_a_valid_item_type
   Inherits when_working_with_the_item_type_repository

   Private _result As Integer
   Private _itemTypeRepository As IItemTypeRepository
   Private _testItemType As ItemType
   Private _itemTypeId As Integer

   Protected Overrides Sub Because_of()
       _result = _itemTypeRepository.Save(_testItemType)
   End Sub

   <Test>
   Public Sub then_a_valid_item_type_id_should_be_returned()
       _result.ShouldEqual(_itemTypeId)
   End Sub
End Clas

Just for reference same code in C#. Test fails

using NBehave.Spec.NUnit;
using NUnit.Framework;
using OSIM.Core;


namespace CSharpOSIM.UnitTests.OSIM.Core
{
    public class when_working_with_the_item_type_repository : Specification
{
}
    public class and_saving_a_valid_item_type : when_working_with_the_item_type_repository
        {
        private int _result;
        private IItemTypeRepository _itemTypeRepository;
        private ItemType _testItemType;
        private int _itemTypeId;

        protected override void Because_of()
        {
            _result = _itemTypeRepository.Save(_testItemType);
        }

        [Test]
        public void then_a_valid_item_type_id_should_be_returned()
        {
            _result.ShouldEqual(_itemTypeId);
        }
    }
}

Test fails on this line:

_result = _itemTypeRepository.Save(_testItemType);

Object reference not set to an instance of an object.

GlutVonSmark
  • 284
  • 2
  • 9
  • 3
    I don't know vb.net but you aren't initializing `_testItemType` in the c# code – Sayse Aug 01 '14 at 09:28
  • 1
    @Sayse, he's not initializing it the the VB.NET code either... Anyway, he's not asking why the test fails, but why it *doesn't fail* in the VB version – Thomas Levesque Aug 01 '14 at 09:35
  • @Sayse *Instantiated [;)](http://stackoverflow.com/questions/2330767/what-is-the-difference-between-instantiated-and-initialized) – Bjørn-Roger Kringsjå Aug 01 '14 at 09:36
  • @Bjørn-RogerKringsjå - *instantiating ;) fair point (thomas too), either way the OP can just enter the last line of his question into google and get more information. – Sayse Aug 01 '14 at 09:39
  • 1
    possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Sayse Aug 01 '14 at 09:40
  • 1
    i know why the test fails in C#. It should fail. – GlutVonSmark Aug 01 '14 at 09:56
  • 1
    @GlutVonSmark, are you sure the test method actually runs? Did you try putting a breakpoint and debugging it? – Thomas Levesque Aug 01 '14 at 10:20
  • @ThomasLevesque struggling to debug in NUnit. Will try to find the reason over the weakend. But when for example I set the value of `_itemTypeId` to some value, 8 for example, test fails because 8 doest equal 0. – GlutVonSmark Aug 02 '14 at 06:07
  • 1
    This part in the vb code does not run while debuggin through code: `Protected Overrides Sub Because_of() _result = ItemTypeRepository.Save(_testItemType) End Sub`. Now need to figure out why – GlutVonSmark Aug 11 '14 at 14:29
  • Did you ever determine why the `Because_of` override was called in C# and not called in VB.NET? Is it still happening for current versions? – Mark Hurd Sep 19 '15 at 04:10

1 Answers1

2

There are subtle differences how value-type variables behave in VB.NET vs. C#.

In C# there is no value assigned automatically when that variable is created; it is null (Nothing). So you can't start using them directly after declaration; the first operation on that variable must be an assignment.

On the other hand, in VB.NET a default value is assigned on its first use. 0 for numbers, False for Boolean, 1/1/0001 12:00 AM for Date, empty string for String etc. They are not null. So you can start using them immediately after declaration.

e.g.

C#:

int i;
i++;        //you can't do this

int j = 0;
j++;        // this works

VB.NET:

Dim i As Integer
i += 1      ' works ok

Dim j As Integer = 0
j += 1      ' this also works

EDIT:

Please read comments about behavior of String type variables.

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
Pradeep Kumar
  • 6,836
  • 4
  • 21
  • 47
  • A `String` is *reference type*, **not** a *value type*. – Bjørn-Roger Kringsjå Aug 01 '14 at 11:03
  • Yes, that's right. But they are designed to behave (mimic) like value-types in vb.net. So that context came in the answer. – Pradeep Kumar Aug 01 '14 at 11:18
  • 2
    Yup! But your statement `..., empty string for String etc. They are not null` is *incorrect*. The default value of an uninstantiated `String` (vb.net) is `Nothing` (null). – Bjørn-Roger Kringsjå Aug 01 '14 at 11:30
  • Just as I said, they behave like value types. Try this: `Dim s As String : If s = "" Then MsgBox("Empty string")`. You will get the messagebox even though you know `s` doesn't contain `""`. All these comparisons will evaluate to True: `s = ""` `s = String.Empty` `s = Nothing` `s Is Nothing` – Pradeep Kumar Aug 01 '14 at 11:39
  • 1
    We're on the same page, and I know all this. My point was that you might want to highlight that string is a special case. Just as you've done in the comments;) – Bjørn-Roger Kringsjå Aug 01 '14 at 11:46
  • 4
    @PradeepKumar: You should state that your answer is strictly concerning local variables - *fields* in both C# and VB are auto-initialized to their default value ('null' for reference types and the default value for value types). Since the original question was about *fields*, I don't think your answer is relevant. – Dave Doknjas Aug 01 '14 at 14:25
  • Assuming this is the right answer. In the VB version I initialize the `_result` integer that gets the value of 0. The same is true for `_itemTypeId`. So `_result.ShouldEqual(_itemTypeId)` gives us 0 is equal to 0. But then why this line `_result = itemTypeRepository.Save(_testItemType)` doesn't make the test file if the `_testItemType` isn't initialized – GlutVonSmark Aug 02 '14 at 06:00
  • 1
    @DaveDoknjas: You are correct. Fields in c# are initialized with default values, same as in VB.NET. So the problem might be somewhere else. Also the line on which he is facing error doesn't involve reading from these fields either. So probably `_itemTypeRepository` or `_testItemType` is not initialized when the program hits that line. – Pradeep Kumar Aug 04 '14 at 10:19
  • 2
    `when that variable is created; it is null` that's not quite true. A value type cannot contain the null value. The compiler will complain that it is "unassigned", but it is not null. – djv Aug 04 '14 at 16:08
  • @PradeepKumar, _it is `null` (`Nothing`)_ - do not use this kind of equality. They are different, if you want show equality of `Nothing` in C# it is then `default(T)`. `Nothing` is simply literal which is default value of type. It is 0 for `Integer`, `False` for `Boolean` and `null` for all reference types - including `string`. `Dim value As String = Nothing` is not equal to `Dim value As String = String.Empty`. As prove you will get `false` when "Dim value As String = Nothing" and compare `If String.Empty.Equals(value) Then`. Another prove: `Dim value As String` and `value.Length`-Exception – Fabio Oct 09 '17 at 06:39
  • 1
    The reason why comparison of `Nothing` to empty string return true - is because in vb.net(only in vb.net) `=` operator uses `StrCmp` method, which convert `Nothing` to string with length = 0. – Fabio Oct 09 '17 at 06:45
  • I can't emphasize any more that `"STRING IS A REFERENCE TYPE"`. Please read the answer and comments from top to bottom. I never said that string is a value type. As already stated, `String is a reference type which mimics behavior of value types in VB.NET` as perceived by end-user. In fact, string doesn't work like other reference types either, under the hood. Many different unrelated strings with same content may be pointing to same memory location which other reference types don't do. Though that's a different discussion altogether! – Pradeep Kumar Oct 09 '17 at 07:53
  • @PradeepKumar - i said nothing about "string is reference type" - My point was that you mistakenly mention that `null` in c# is same as `Nothing` in vb.net. Also explained your wrong assumptions that default value of `string` is empty string. – Fabio Oct 09 '17 at 10:51