2009-10-13 10 views
11

Czcionka, która jest niezmienna, powoduje problemy zarówno programisty, jak i GC, ponieważ za każdym razem trzeba utworzyć nową instancję.Dlaczego czcionka jest niezmienna?

Dlaczego czcionka to niezmienny typ odniesienia?

+1

Zgadzam się, że coś w rodzaju 'Label1.Font = new Font (Label1.Font.Name, Label1.Font.Size + 2.0F, Label1.Font.Style, Label1.Font.Unit);' wydaje się nieco ponad u góry z perspektywy "po prostu rób, co chcę". – Greg

+0

Umożliwia niezmienne numery kart kredytowych, aby każdy mógł zmienić ich numer w dowolnym momencie !!! co za zabawa. I chociaż dodajesz - pozwalamy, aby imię każdego było niezmienne, abyśmy mogli zmieniać je co 5 minut, jeśli chcemy. –

Odpowiedz

28

Upraszcza korzystanie z systemu renderowania.

Jeśli struktura pozwoliła na zmianę czcionki, będzie musiała wykryć zmiany i przerobić sposób ich renderowania w regularnych odstępach czasu. Ponieważ Font tworzy rodzimy zasób, utrzymanie tego niezmiennego uniemożliwia systemowi martwienie się o konieczność wielokrotnego odtworzenia uchwytów w sposób powtarzalny.

Ponadto, nie zgadzam się pod względem "Distress to the programmer". Dzięki niezmiennej czcionce staje się bardziej oczywiste, co się dzieje, gdy użytkownik tworzy obiekt czcionki. Jeśli chcesz nową czcionkę, musisz utworzyć nowy obiekt czcionki, który z kolei tworzy nowe rodzime zasoby czcionek. Uczynienie Czcionki niezmienną sprawia, że ​​staje się bardziej jasne, co się dzieje - mniej prawdopodobne jest przypadkowe spowodowanie problemu z wydajnością.

Gdy czcionka była zmienna, mniej oczywiste byłoby tworzenie uchwytów wielokrotnie podczas zmieniania właściwości czcionki.

+0

Nie wspominając, że jakikolwiek obiekt (np. Okno), który używa zarządzanego obiektu czcionki, musiałby wykryć, kiedy uchwyt macierzysty został zmieniony i powiązać nowy uchwyt z własnym rodzimym obiektem (np. HWND). –

+1

Zawsze uważałem, że kopiowanie i nieznaczne zmienianie istniejącego obiektu czcionki było niepotrzebnie bolesne. Nigdy nie uważałem, że tworzą natywne zasoby, więc +1 za wnikliwą odpowiedź. – Greg

+0

Szkoda, że ​​nie zrobili żadnej metody AsBold(), która zwraca nową instancję tylko pogrubioną czcionką. – Letterman

8

Nie są to struktury, ponieważ muszą mieć finalizatory do zawijania obiektów leżących pod nimi i zapewniać rozsądną implementację IDisposable. Co stanie się, jeśli masz swoją własną kopię numeru struct? Czy za każdym razem klonujesz uchwyt?

To naprawdę nie jest dużo stresu na GC ...

Pozwala również Font być ponownie używane bezpiecznie bez obaw o to zmieniając półmetku operację ;-P

+0

Co mogłoby być pomocne byłoby mieć zmienną strukturę FontInfo i niezmienną klasę ReadyFont; tylko ta ostatnia musiałaby się pozbyć. Rzeczy takie jak właściwości czcionki na elementach sterujących byłyby wyświetlane jako struktura FontInfo, a nie jako ReadyFont. – supercat

4

I nie zgadzam się z tym, co utrudnia programistę. W BCL jest wiele niezmiennych typów, które są używane codziennie przez programistów i nie powodują żadnych problemów. System.String na przykład.

Jedną z zalet niezmienności jest to, że za każdym razem nie trzeba tworzyć nowej instancji. Możesz ponownie użyć tego samego rodzaju czcionki tak często, jak chcesz, ponieważ to się nie zmieni. Z drugiej strony, jeśli byłaby zmienna, musiałbyś za każdym razem sporządzać kopię, aby zagwarantować, że nikt inny nie zmieni tego pod tobą.

Wreszcie, czcionka nie jest tak naprawdę niezmienną klasą w ścisłym znaczeniu tego słowa. Implementuje IDisposable, a w metodzie Dispose rozdziera bazowy obiekt natywny.

+0

To przypomina mi coś, co zastanawiałem się: kto "posiada" czcionki, obrazy i inne obiekty używane w kontrolkach? Jeśli utworzę czcionkę i przypisze ją do właściwości czcionki kontrolki, czy skopiuje ona przekazaną czcionkę, więc powinienem ją wyrzucić, gdy już jej nie potrzebuję, lub powinienem zachować odniesienie do czcionki, dopóki nie wyrzucę kontroli lub przypisać mu inną czcionkę, więc mogę poprawnie usunąć czcionkę? Moim normalnym podejściem jest po prostu porzucenie obiektów, które przypisuję do kontroli, i pozwolić GC je obsłużyć, ale to wydaje się niedorzeczne. – supercat

+0

@supercat Nigdy nie zrozumiałem odpowiedzi, kto jest właścicielem 'Font' i nie wierzę, że jest dobra odpowiedź. Mam takie samo podejście porzucenia i niech GC je zbierze. – JaredPar

+0

Zapomniałem, czy powiedziałem to wcześniej, ale właściwość czcionki kontrolki wydaje się próbkować właściwości czcionki bez względu na to, czy czcionka została usunięta. Można usunąć obiekt czcionki i nadal ustawić właściwość Control.Font na usuwaną czcionkę. – supercat

13

Zadaj sobie kilka pytań.

Po pierwsze, czy jest to czcionka logicznie coś zmiennego, jak lista zakupów, czy niezmienna rzecz, jak liczba? Jeśli modelujesz listę zakupów w programie, warto ją zmienić, ponieważ zazwyczaj myślisz o posiadaniu jednej listy zakupów, której zawartość zmienia się wraz z wyczerpaniem lub zakupem poszczególnych produktów. Ale liczby, które zazwyczaj modelujesz jako niezmienne - liczba 12 to liczba 12, teraz i na zawsze.

Myślę, że "Helvetica 12 point bold" to stała, niezmienna rzecz, jak liczba, a nie coś, co mogę zmienić.

Po drugie, czy jest to czcionka logicznie bardziej podobna do wartości, z której można tworzyć kopie, czy jest to bardziej jak pojedyncza rzecz, do której można się odnieść?Nie myślę o "dwóch kopiach" Helvetica; Myślę o nawiązywaniu do Helvetica. Podczas gdy liczby, o których myślę, że mają różne kopie dla różnych celów - kiedy mam 12 pozycji na mojej liście zakupów i 12 kluczy na moim kluczyku, nie myślę o obu tych rzeczach jako "odnoszących się do 12".

Ponieważ uważam, że czcionki są niezmienne i odnoszone do nich, a nie jako zmienne i kopiowane według wartości, osobiście modelowałbym czcionki jako niezmienne typy odniesienia. Być może twoje intuicje dotyczące czcionek są inne niż moje.

+0

Twoja filozofia leczenia rzeczy wydaje mi się irytująco niespójna. ale mogłem coś przeoczyć ... Najpierw porównujesz ogólną listę zakupów do określonego numeru. można również powiedzieć, że "arbuz, ser, chleb" zawsze będzie "arbuz, ser i chleb", a liczba taka jak cena, może być bardzo zmienna ....... liczba może wydawać się bardziej atomowa dla nas ludzie, ale lista zakupów to istota, tak jak liczba jest bytem, ​​oba są zmienne i niezmienne w zależności od kontekstu. tak jak prawda zawsze będzie prawdą, ale lampa może być włączona lub wyłączona ...... [kontynuacja] – Letterman

+0

[część 2] jest teraz logiczna LOGICZNIE niezmienna? to pytanie nie ma odpowiedzi. jedyne rzeczy, które mają znaczenie, to rozważania praktyczne ............. teraz "Helvetica 12 point bold" jest tak naprawiona. tak jak prawda i numer 12. ale czcionka mojego tytułu jest zmienna, tak jak cena samochodu lub stanu baranka ...... po drugie, w rzeczywistości MOŻESZ mieć w C# dwie kopie " Helvetica 12 pkt. Pogrubiony "i ty SĄ to numery odsyłające w języku java ........ logika powinna być czynnikiem, który pomaga osiągnąć estetyczne wyniki, ale na końcu powinieneś kierować się praktyczną uwagą. – Letterman

+2

@Itay: Kiedy moja żona prosi mnie o dodanie mleka do listy zakupów, nie niszczę starej listy i nie produkuję nowej listy z dodatkiem mleka. Lista jest zmienna, więc warto modelować listę zakupów o zmiennym typie. Istnieją oczywiście konteksty, w których listy modelowania jako niezmienne mają sens. –

0

Można się spierać, że problem dotyczy programisty. Ale w przeciwnym przypadku można by również postawić ten sam argument.

Na przykład:

// Let me just set the button to the same font as the textbox... 
button.Font = textBox.Font; 

// ...except that I want the button's font to be bold. 
button.Font.Bold = true; 

Powyższy kod będzie ustawić przycisk i czcionki pola tekstowego do pogrubione w tym samym czasie, gdy Font były zmienne, w przeciwieństwie do oczekiwań autora.

0

Czcionka jest źle zaprojektowanym obiektem, który narusza zasadę odpowiedzialności pojedynczej, a trudności, które wymieniasz, wynikają z tego. Problem z czcionką polega na tym, że obejmuje ona dwie rzeczy: (1) opis sposobu rysowania czcionki oraz (2) obiekt czcionki GDI dla czcionki z tymi właściwościami. Poprzedni typ może być zmienny bez konsekwencji, a sprawienie, że ten drugi będzie zmienny, będzie stwarzał różne problemy.

Pomiędzy innymi należy zastanowić się, w jaki sposób należy śledzić własność typowej właściwości czcionki sterującej (np. Przycisku)? Jeśli czasami zmienisz czcionki skojarzone z kontrolkami, powinieneś stworzyć osobny obiekt czcionki dla każdej kontrolki, a następnie pozbyć się go przy zmianie czcionki kontrolki na coś innego lub zachować listę wszystkich różnych czcionek, których używasz, aby uniknąć tworzenia nadmiernej liczby identycznych obiektów czcionek, czy co?

Jeśli istniała struktura FontDescription (która była zmienna, a nie identyfikowalna) i rzeczy takie jak Control.Font były typu FontDescription (lub jeszcze lepiej, Control wyeksponował metodę SetFont z parametrem typu FontDescription), powyższe pytanie mogłoby odpowiedzieć po prostu. W tej sytuacji najbardziej efektywnym sposobem ustawienia Czcionki kontrolki jest utworzenie nowego obiektu czcionki (jeśli jeszcze nie jest odpowiedni), natychmiast go usuń, a następnie wykonaj zadanie. "Czcionka" część czcionki pozostaje quasi-ważna nawet po Disposal, i to wszystko, co jest naprawdę potrzebne dla właściwości Control.Font.