Po co używać publicznej metody w klasie wewnętrznej?

W jednym z naszych projektów jest dużo kodu, który wygląda tak:

internal static class Extensions
{
    public static string AddFoo(this string s)
    {
        if (!string.IsNullOrEmpty(s)) return s + "Foo";
        return "Foo";
    }
}

Czy Jest jakiś wyraźny powód, aby to zrobić, inny niż "łatwiej jest upublicznić Typ później?"

Podejrzewam, że ma to znaczenie tylko w bardzo dziwnych przypadkach krawędzi (odbicie w Silverlight) lub wcale.

Author: Eric Burcham, 2012-02-16

10 answers

Aktualizacja: to pytanie było tematem mojego bloga we wrześniu 2014. Dzięki za świetne pytanie!

Istnieje spora debata na ten temat nawet w samym zespole kompilatorów.

Po pierwsze, mądrze jest zrozumieć zasady. Publiczny element klasy lub struktury jest elementem dostępnym dla wszystkiego, co ma dostęp do typu zawierającego . Tak więc publiczny członek klasy wewnętrznej jest faktycznie wewnętrzny.

Więc teraz, biorąc pod uwagę wewnętrzne klaso, czy jego członkowie, do których chcesz mieć dostęp w Zgromadzeniu, powinni być oznaczeni jako publiczni czy wewnętrzni?

Moim zdaniem: Oznacz takich członków jako publicznych.

Używam słowa "public", aby oznaczać "ten członek nie jest szczegółem implementacji". Protected member jest szczegółem implementacji; jest w nim coś, co będzie potrzebne, aby Klasa pochodna działała. Wewnętrzny członek jest szczegółem realizacji; coś innego wewnętrznego do tego zgromadzenia potrzebuje członka w celu pracy prawidłowo. Członek publiczny mówi: "ten członek reprezentuje kluczową, udokumentowaną funkcjonalność dostarczaną przez ten obiekt."

Zasadniczo, moja postawa jest taka: przypuśćmy, że zdecydowałem się uczynić tę wewnętrzną klasę klasą publiczną. Aby to zrobić, chcę zmienić dokładnie jedną rzecz : dostępność klasy. Jeśli przekształcenie klasy wewnętrznej w klasę publiczną oznacza, że muszę również zamienić członka wewnętrznego w członka publicznego, to ten członek był częścią powierzchni publicznej obszar klasy, a w pierwszej kolejności powinien być publiczny.

Inni się nie zgadzają. Istnieje kontyngent, który mówi, że chcą mieć możliwość spojrzenia na deklarację członka i natychmiast wiedzieć, czy będzie ona wywoływana tylko z kodu wewnętrznego.

Niestety, to nie zawsze działa ładnie; na przykład, wewnętrzna klasa, która implementuje wewnętrzny Interfejs nadal musi mieć elementy implementujące oznaczone jako publiczne, ponieważ One są częścią powierzchni publicznej klasy .

 332
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-15 16:39:43

Jeśli klasą jest internal, nie ma znaczenia z punktu widzenia dostępności, czy oznaczasz metodę internal czy public. Jednak nadal dobrze jest użyć typu, którego byś użył, gdyby klasa była public.

Podczas gdy niektórzy mówią, że ułatwia to przejście z internal do public. Służy również jako część opisu metody. Internal metody są zazwyczaj uważane za niebezpieczne dla nieograniczonego dostępu, podczas gdy metody public są uważane za (głównie) darmowe gry.

Za pomocą internal lub public tak jak w klasie public, zapewniasz, że przekazujesz, jakiego stylu dostępu należy się spodziewać, a jednocześnie ułatwiasz pracę wymaganą do stworzenia klasy public w przyszłości.

 14
Author: Guvante,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 22:18:43

Często zaznaczam moje metody w klasach wewnętrznych publicznych zamiast wewnętrznych jako a) to naprawdę nie ma znaczenia i b) używam wewnętrznych, aby wskazać, że metoda jest wewnętrzna celowo (jest jakiś powód, dla którego nie chcę ujawniać tej metody w klasie publicznej. Dlatego, jeśli mam wewnętrzną metodę, naprawdę muszę zrozumieć powód, dla którego jest wewnętrzna, zanim zmienię ją na publiczną, podczas gdy jeśli mam do czynienia z publiczną metodą w klasie wewnętrznej, naprawdę muszę pomyśleć o tym, dlaczego Klasa jest wewnętrzna, w przeciwieństwie do tego, dlaczego każda metoda jest wewnętrzna.

 10
Author: Ɖiamond ǤeezeƦ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 22:18:20

Podejrzewam, że " łatwiej jest upublicznić Typ później?"jest.

Reguły zakresów oznaczają, że metoda będzie widoczna tylko jako internal - więc tak naprawdę nie ma znaczenia, czy metody są oznaczone public czy internal.

Jedną z możliwości, która przychodzi mi na myśl, jest to, że klasa była Publiczna, a później została zmieniona na internal i deweloper nie zadał sobie trudu, aby zmienić wszystkie modyfikatory dostępności metod.

 8
Author: Oded,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 22:10:46

W niektórych przypadkach może się zdarzyć, że typ wewnętrzny implementuje publiczny interfejs, co oznaczałoby, że wszelkie metody zdefiniowane w tym interfejsie nadal muszą być zadeklarowane jako publiczne.

 6
Author: Trevor Pilley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 22:36:25

To to samo, metoda publiczna będzie tak naprawdę oznaczona jako wewnętrzna, ponieważ jest wewnątrz wewnętrznej klasy, ale ma przewagę (jak się domyślasz), jeśli chcesz oznaczyć klasę jako publiczną, musisz zmienić mniej kodu.

 2
Author: Mario Corchero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 22:13:07

internal mówi, że członek może być dostępny tylko z tego samego zgromadzenia. Inne klasy w tym zbiorze mogą uzyskać dostęp do członka internal public, ale nie będą mogły uzyskać dostępu do członka private lub protected, internal lub nie.

 0
Author: Ryan P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 22:10:39

Zmagałem się z tym dzisiaj. Do tej pory powiedziałbym, że wszystkie metody powinny być oznaczone internal, jeśli klasa jest internal i rozważałbym cokolwiek innego po prostu złe kodowanie lub lenistwo, szczególnie w rozwoju przedsiębiorstw; jednak musiałem podklasować klasę A public i nadpisać jedną z jej metod:

internal class SslStreamEx : System.Net.Security.SslStream
{
    public override void Close()
    {
        try
        {
            // Send close_notify manually
        }
        finally
        {
            base.Close();
        }
    }
}

Metoda musi być public i dało mi do myślenia, że nie ma logicznego sensu ustawiać metod jako internal chyba, że naprawdę muszą być, jako Eric Lippert powiedział (a):

Do tej pory nigdy nie przestałem o tym myśleć, po prostu to zaakceptowałem, ale po przeczytaniu postu Erica naprawdę dało mi to do myślenia i po wielu rozważaniach ma to sens.

 0
Author: Storm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-26 15:26:34

Jest różnica. W naszym projekcie zrobiliśmy wiele klas wewnętrznych, ale wykonujemy testy jednostkowe w innym zestawie i w naszej informacji o montażu użyliśmy InternalsVisibleTo, aby umożliwić UnitTest assembly wywołanie klas wewnętrznych. Zauważyłem, że jeśli wewnętrzna klasa ma wewnętrzny konstruktor, nie jesteśmy w stanie utworzyć instancji za pomocą aktywatora.CreateInstance w zestawie testów jednostkowych z jakiegoś powodu. Ale jeśli zmienimy konstruktor NA public, ale klasa jest nadal wewnętrzna, to działa dobrze. Ale myślę, że jest to bardzo rzadki przypadek(jak Eric powiedział w oryginalnym poście: odbicie).

 0
Author: Farrah Jiang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-13 03:58:30

Myślę, że mam dodatkowe zdanie na ten temat. Na początku zastanawiałem się, jak to ma sens, aby ogłosić coś publicznie w klasie wewnętrznej. Więc skończyłem tutaj, czytając, że może być dobrze, jeśli później zdecydujesz się zmienić klasę na publiczną. Prawda. Tak więc, wzór uformowany w moim umyśle: jeśli nie zmienia obecnego zachowania, to być permissive, i pozwolić rzeczy, które nie ma sensu (i nie boli) w obecnym stanie kodu, ale później byłoby to, jeśli zmienisz deklarację klasy.

Tak:

public sealed class MyCurrentlySealedClass
{
    protected void MyCurretlyPrivateMethod()
    {
    }
}

Zgodnie z "wzorcem", o którym wspomniałem powyżej, powinno być idealnie. Podąża za tym samym pomysłem. Zachowuje się jak Metoda private, ponieważ nie można dziedziczyć klasy. Ale jeśli usuniesz ograniczenie sealed, nadal jest ono ważne: odziedziczone klasy mogą zobaczyć tę metodę, co jest absolutnie tym, co chciałem osiągnąć. Ale dostajesz Ostrzeżenie: CS0628, lub CA1047. Oba są o nie deklarować protected członków w klasie sealed. Co więcej, znalazłem pełną zgodę, co do tego, że jest to bezsensowne: 'Protected member in sealed class' Ostrzeżenie (Klasa singleton)

Więc po tym ostrzeżeniu i dyskusji związanej, zdecydowałem się zrobić wszystko wewnętrzne lub mniej, w klasie wewnętrznej, ponieważ to odpowiada bardziej tego rodzaju myślenia, a my nie mieszamy różnych "wzorców".

 0
Author: Hix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-19 11:06:18