GetHashCode

Metoda w obiekcie GetHashCode() służy do generowania prostego (Int32) skrótu danego obiektu. We własnych klasach powinniśmy ją nadpisać, szczególnie jeśli dane obiekty będą wykorzystywane w kolekcjach typu Dictionary i HashSet.
Jednak powinniśmy zrobić to prawidłowo, przestrzegając 3 prostych zasad:

  1. Jeśli dwa obiekty są sobie równe muszą zwracać ten sam skrót, ale jeśli są różne powinny (ale nie muszą) zwracać różne skróty.
  2. Każdy obiekt powinien zwracać ten sam skrót, dopóki nie został zmodyfikowany jego stan, w ten sposób, że metoda Equals zwracałaby inną wartość, w stosunku do obiektu, z którym był wcześniej równy.
  3. Zwracany skrót powinien być jak najbardziej losowy, opierając się na istotnych polach tego obiektu.

Dzisiejszy post powstał dlatego, że źle napisałem metodę GetHashCode() i dziwnym sposobem Dictionary nie mógł odnaleźć klucza, który przecież był w słowniku! ;]
Dokładniej, metodę GetHashCode oparłem m.in. o pole, które jest bardzo często zmieniane. Było to pole z datą rozpoczęcia zadania na wykresie Gantta. Jeśli przesunąłem zadanie, obiekt generował już inny skrót. Więc nie mogłem obiektu znaleźć w słowniku, który sobie cache'uje skróty, żeby za każdym razem ich od nowa nie liczyć.

Podsumowując: GetHashCode() powinien być oparty o stałe pola, takie jak identyfikator, nazwa która nie może być zmieniona lub inne pola, których zmiana jest jednoznaczna z tym, że jest to już inny obiekt względem metody Equals, którą też powinniśmy odpowiednio nadpisać ;)

Zamiana tablicy byte'ów na "HEXy" i vice versa (C#)

Podążając za poprzednim wpisem, zamieszczam dwie przydatne metody do zamiany tablicy byte'ów (byte[]) na zapis szesnastkowy w stringu oraz metodę odwrotną. Metody są całkiem szybkie, na pewno wiele wydajniejsze od używania ToString("x2") czy Convert.ToByte(...).
Moja metoda BytesToHex() jest wzorowana na metodzie BitConverter.ToString(), która to niestety przymusowo wstawia nam kreski między każdym bajtem w zapisie szesnastkowym.
Natomiast moje HexToBytes() działa odwrotnie ;-)

Czytaj dalej...

Szybkie porównywanie dwóch tablic byte'ów (C#)

Dziś krótka notka. Przedstawię tylko szybką metodę do porównywania dwóch tablic byte'ów. Wykorzystuje ona wskaźniki (czyli wymaga użycia trybu unsafe), gdzie po odpowiednich rzutowaniach, porównujemy 64bitowe longi. Daje nam to około 5-10 krotne przyśpieszenie, w porównaniu do zwykłego porównywania byte'ów w pętli for.

Czytaj dalej...

Jak wyrównać tekst do prawej strony w ComboBox? (C# / .NET)

Jeśli w kontrolce ComboBox trzymamy liczby, dobrze by było, aby były one wyrównane do prawej strony. W TextBox odpowiada za to właściwość TextAlign, niestety kontrolka ComboBox nie została wyposażona w ową funkcjonalność.
Po wspaniałomyślnej inicjatywie kolegi, który zmienił właściwość RightToLeft = true (*), sam wziąłem się za wymyślenie czegoś ;)

(*) - właściwość używana tylko i wyłącznie dla języków pisanych od prawej do lewej strony

Osiągnąłem tylko częściowy sukces, czyli najlepiej działa jeśli kontrolkę ustawimy na DropDownList. Ponieważ, kiedy umożliwimy edycję tekstu (jak w TextBox) to tekst będzie po lewej stronie, ale w rozwijanej liście już po prawej. Ale jeśli damy tylko możliwość wyboru elementów z listy (czyli DropDownList) wszystko będzie po prawej stronie.
Oto "bardzo" przykładowy kod:

Czytaj dalej...

Where() vs. FindAll()

Od jakiegoś czasu technologia LINQ na dobre się zadomowiła w moim projekcie w pracy. Oprócz LINQ to SQL, również LINQ to Objects, a razem z nim zrodziło się pytanie…

Co jest wydajniejsze: wyszukiwanie przez List.Where() czy List.FindAll() ?

Dziś znalazłem odrobinę czasu i postanowiłem napisać prosty programik testujący.

Na początek 2 metody mierzące czas:

private static DateTime dt = DateTime.Now;

public static void StartTimer()
{
        dt = DateTime.Now;
}

public static void EndTimer(string text)
{
        Console.WriteLine(”\r\n {0}\r\nCzas: {1} ms”, text, (DateTime.Now – dt).TotalMilliseconds);
}

Następnie stworzyłem dużą listę z losowymi wartościami:

Czytaj dalej...

Reinżynieria kontrolki PrintPreviewControl

Wczoraj natknąłem się na dosyć nietypowy problem. Otóż, jest sobie kontrolka
PrintPreviewControl, która najzwyczajniej w świecie generuje podgląd wydruku dla wybranego PrintDocument. Działa normalnie – jak zwyczajny podgląd wydruku w większości programów.

Kontrolka ma pewien „fjuczer” – podczas generowania podglądu, na chwilkę pojawia się okienko, jakiś StatusDialog. „Fjuczer” ów, jak można się domyśleć, był przeze mnie niepożądany.

Czytaj dalej...