Od około półtora roku pracuję w projekcie, który początkowo był napisany w Vb.Net, ale teraz nowszy kod jest tworzony w C#. To świetny przykład tego, jak jeden projekt można napisać w dwóch językach, a kod w Vb.Net może odwoływać się do C# i na odwrót.
Vb.Net i C# są bardzo podobne i są kompilowane do tego samego języka pośredniego, ale niektóre różnice są bardziej zaskakujące niż inne.
Proste różnice
Zacznijmy od rzeczy oczywistych. Vb.Net używa prostego języka angielskiego w swojej składni, podczas gdy C# używa składni opartej na C. Spójrzmy na przykład.
private string ReplaceAnd(string s) { if (s != null && s.Contains(":")) return s.Replace(":", "?"); return s; }
A teraz ten sam przykład w Vb.Net:
Private Function ReplaceAnd(s As String) As String If s IsNot Nothing And s.Contains(":") Then Return s.Replace(":", "?") End If Return s End Function
Przyzwyczajenie się do deklarowania typów za pomocą słowa kluczowego As
zajęło mi trochę czasu. Także If
potrzebuje słowa Then
, ale to są rzeczy, które piszesz raz lub dwa razy i staje się to nawykiem.
Moim zdaniem największe zmiany przy porównaniu C # z Vb.Net to:
- nie używamy nawiasów do bloków kodu
- nie ma potrzeby umieszczania średników na końcu instrukcji
- nazwy zmiennych nie uwzględniają wielkości liter
- i kilka innych 😃
&& vs And vs AndAlso
Wszystkie te proste różnice to tylko różnice w składni języka, ale zasadniczo kod pozostaje taki sam. Jednym z moich największych błędów podczas pisania kodu Vb.Net było użycie operatora And
jako &&
z C#. Chodzi o to, że te dwa operatory nie są równoznaczne.
Spójrzmy na przykład. Użyję dwóch metod, które sprawdzają wartość null
w instrukcji If
i dokonają podmiany ciągu znaków.
Private Function ReplaceAndAlso(s As String) As String If s IsNot Nothing AndAlso s.Contains(":") Then Return s.Replace(":", "?") End If Return s End Function Private Function ReplaceAnd(s As String) As String If s IsNot Nothing And s.Contains(":") Then Return s.Replace(":", "?") End If Return s End Function
Różnica pomiędzy And
i AndAlso
jest następująca:
And
sprawdzi warunek po prawej stronie, nawet jeśli warunek po lewej stronie jest fałszywyAndAlso
nie sprawdzi warunku po prawej stronie, jeśli ten po lewej jest fałszywy
Aby to zobrazować, napisałem testy jednostkowe:
<TestCase("abc:d", "abc?d")> <TestCase(Nothing, Nothing)> Public Sub AndAlsoTest(toReplace As String, expected As String) ReplaceAndAlso(toReplace).Should().Be(expected) End Sub <TestCase("abc:d", "abc?d")> <TestCase(Nothing, Nothing)> Public Sub AndTest(toReplace As String, expected As String) ReplaceAnd(toReplace).Should().Be(expected) End Sub
A rezultaty są następujące:
AndTest
kończy się niepowodzeniem, ponieważ operator And
sprawdza zarówno warunek po lewej, jak i po prawej stronie, co powoduje wyjątek NullReferenceException
. Więc jeśli chcesz sprawdzić wartość null
w instrukcji If
i zrobić coś innego, po prostu użyj AndAlso
.
Wymuszenie przekazania zmiennej przez wartość
Może nie jest to duża różnica, ale byłem zaskoczony, że da się to zrobić.
Przyjrzyjmy się prostemu kodowi i dwóm testom:
<Test> Public Sub AddTest() Dim a As Integer = 5 Dim result = Add(a) a.Should().Be(6) result.Should().Be(6) End Sub <Test> Public Sub AddByValueTest() Dim a As Integer = 5 Dim result = Add((a)) a.Should().Be(5) result.Should().Be(6) End Sub Public Function Add(ByRef x As Integer) As Integer x = x + 1 Return x End Function
Mamy prostą metodę Add
, w której zwiększamy podaną wartość o 1. Przekazujemy tę zmienną przez referencję, więc również należy ją zmienić.
Zauważ, że w AddByValueTest
przekazujemy (a)
i w ten sposób możemy przekazać zmienną przez wartość. Zauważ, że działa to tylko dla typów wartościowych.
A wyniki dowodzą, że tak naprawdę działa:
Zamiana enum na string
Ta różnica mnie zaskoczyła, kiedy ją zobaczyłem i była to ostateczna motywacja do napisania tego postu. Robiłem refaktoryzację wokół Vb.Net z konwersją enum-ów, a mój kolega przeglądał zadanie i powiedział.
– Hej, fajna refaktoryzacja, ale obawiam się, że może nie zadziałać. – powiedział kolega.
– Naprawdę? Uruchomiłem ten kod i działał poprawnie. – Powiedziałem.
– Lepiej sprawdź to jeszcze raz, dla pewności napisałem nawet test jednostkowy. – powiedział kolega.
Rzućmy okiem na ten test. Konwertuję enum na ciąg znaków.
public enum ProfileType { Person = 1, Company = 2 } [Test] public void ConvertEnumTest() { Convert.ToString(ProfileType.Company).Should().Be("2"); }
A kiedy go uruchomisz, zawodzi, mój kolega miał rację. 😲
Jednak byłem podejrzliwy i kod, który napisałem był w Vb.Net, a nie w C#, więc napisałem kolejny test. Ale tym razem w Vb.Net.
<Test> Public Sub ConvertEnumTest() Convert.ToString(ProfileType.Company).Should().Be("2") End Sub
I wiesz co? Przechodzi!
Więc mój oryginalny kod był poprawny. Jednak Convert.ToString()
na enum działa inaczej w Vb.Net i C#.
Summary
Praca z Vb.Net brzmi jak powrót do średniowiecza, ale w rzeczywistości dość szybko przyzwyczaiłem się do składni Visual Basic. Możliwości obu są bardzo podobne, ponieważ pod spodem nadal jest ten sam kod, ale C# wydaje mi się nieco bardziej zwięzły i intuicyjny. Może dlatego, że w szkole wolałem C++ od Pascala 😁
Mam nadzieję, że post Ci się podobał, miłego dnia! 😊