25/11/2010

Czemu VB.NET jest be?

Home

Z językiem VB.NET da się pracować, co z powodzeniem czynię od blisko roku, ale niektóre rzeczy doprowadzają mnie do szału. Aby wyjaśnic o co chodzi posłużę się bardzo, bardzo prostym interfejsem pokazanym poniżej:
Public Interface IFun
  Function Fun() As Integer
  Function SuperFun() As Integer
End Interface
Implementacja funkcji Fun oraz SuperFun jest trywialna i wyglądają jak poniżej:
Public Function Fun() As Integer
  Return 0
End Function

Public Function SuperFun() As Integer
  Return 1
End Function
Jeszcze kod, który korzysta z tej implementacji:
Sub Main()
  Dim fun As Fun = New Fun()
  Dim ifun As IFun = fun

  Console.WriteLine(fun.Fun() = ifun.Fun())
  Console.WriteLine(fun.SuperFun() = ifun.SuperFun())
  Console.WriteLine(fun.Fun() = ifun.SuperFun())
  Console.WriteLine(fun.SuperFun() = ifun.Fun())
End Sub
A na koniec pytanie, jaki wynik zostanie wypisany na ekan? Założę się, że nikt się nie zawacha i odpowie:
True
True
False
False
Taki wynik jest oczywiście logiczny i prawidłowy ale nie zawsze, w przypadku VB.NET można uzyskać również taki wynik:
False
False
True
True
Nie trzeba do tego stosować żadnych sztuczek, wystarczy zwykła pomyłka. Pokazując implementację metod Fun oraz SuperFun celowo pominąłem słowo kluczowe Implements, które określa jaki element intefejsu implementuje dana metoda. Kod klasy powinien wyglądać tak:
Public Class Fun
  Implements IFun

  Public Function Fun() As Integer Implements IFun.Fun
    Return 0
  End Function

  Public Function SuperFun() As Integer Implements IFun.SuperFun
    Return 1
  End Function
End Class
Niestety ponieważ metody Fun oraz SuperFun mają takie same sygnatury to nic nie stoi na przeszkodzie aby zamienić miejscami Implements IFun.Fun z Implements IFun.SuperFun i otrzymać coś takiego:
Public Class Fun
  Implements IFun

  Public Function Fun() As Integer Implements IFun.SuperFun
    Return 0
  End Function

  Public Function SuperFun() As Integer Implements IFun.Fun
    Return 1
  End Function
End Class
Mały, wkurzajacy i bardzo trudny do wykrycia błąd wynikający z cech języka VB.NET.

5 comments:

Anonymous said...

W większości języków programowania nazwa metody jest częścią jej sygnatury. Panuje także zasada, że metoda implementująca musi mieć taką samą sygnaturę jak metoda implementowana. Zapewne projektanci VB.NET chcieli dać programistom większą elastyczność w tej kwestii. Jednak, jak pokazuje opisany przez Ciebie przykład, może powodować to trudne do wykrycia błędy. Moim zdaniem rachunek zysków i strat jest na minus dla takiej elastyczności.

Yuras said...

Też nigdy nie przepadałem za VB.Net, a jeśli już coś musiałem robić to była to w sumie dla mnie męka... Sama semantyka tego języka jakoś mnie odrzuca, bo wszystko jednak inaczej niż np. w Javie, C# czy też C++, które w sumie można powiedzieć dominują na dzisiejszym rynku.

Yuras said...

P.S. Przydałby się jakiś link do strony głównej w nagłówku, albo gdzieś w widocznym miejscu u góry:) Ale to oczywiście drobiazg

Michał Komorowski said...

Przestawienie się na VB.NET zajęło mi mało czasu i teraz posługuję się nim biegle. Przyznam jednak, że nawet teraz, czyli po prawie roku pracy z tym językiem, cały czas muszę się zastanawiać jak użyć niektórych konstrukcji językowych. Sądzę, że wbrew zamierzeniem twórców ten język wcale nie jest intuicyjny, a upodabnianie go do języka naturalnego tylko wyszło mu na gorsze.

PS.

Dodałem link do strony głównej pod tytułem posta. Dzięki za wskazówkę. Taki link znajdował się już u dołu postu ale rzeczywiście ciężko go dostrzec.

Anonymous said...

widze że nie jestem odosobniony w swojej niechęcie do VB.NET, dodam jeszcze że VB.NET nie ma wszyststkich "ficzerów" C# (.NET 3.5), na przykład anonymous properties (pewnie jest tego więcej, ale nic nie przychodzi mi do głowy)

dodatkowo wydaje mi się że Visual Studio (VS2008) lepiej współpracuje z C#:
- mam wrażenie że podpowiedzi pojawiają się wolniej w przypadku C#
- podpinanie eventów, w C# to +=, 2 x TAB i załatwione, w VB tak łatwo już nie jest
- natomiast do szału doprowadza mnie VS kiedy deklaruję zmienną jak poniżej:
Dim zmienna as List(Of JakisTyp) = new (i tutaj brak podpowiedzi ze strony VS) - uprzedzając komentarze, znam składnie
Dim zmienna as New List(Of JakisTyp) - ale jej nie lubie

Post a Comment