Praktyczne zastosowania słowa kluczowego "wewnętrzne" w języku C#

Czy mógłbyś wyjaśnić, jakie są praktyczne zastosowania słowa kluczowego internal W C#?

Wiem, że modyfikator internal ogranicza dostęp do bieżącego zestawu, ale kiedy mogę go potrzebować?

Author: Danny Beckett, 2008-10-03

22 answers

Narzędzia lub pomocnicze klasy/metody, do których chcesz uzyskać dostęp z wielu innych klas w tym samym złożeniu, ale które chcesz upewnić się, że kod w innych złożeniach nie może uzyskać dostępu.

From MSDN:

Powszechne użycie dostępu wewnętrznego jest w rozwoju opartym na komponentach, ponieważ umożliwia grupie komponentów współpracę w sposób prywatny bez narażania się na resztę kodu aplikacji. Na przykład framework do budowania graficznego użytkownika interfejsy mogłyby zapewnić klasy kontrolne i formowe, które współpracują przy użyciu członków z dostępem wewnętrznym. Ponieważ członkowie ci są wewnętrzni, nie są narażeni na działanie kodu używającego frameworka.

Możesz również użyć wewnętrznego modyfikatora wraz z InternalsVisibleTo atrybut assembly level do tworzenia zestawów "friend", którym przyznano specjalny dostęp do wewnętrznych klas zestawu docelowego.

Może to być przydatne do tworzenia zespołów testów jednostkowych, które są następnie możliwość wezwania wewnętrznych członków Zgromadzenia do sprawdzenia. Oczywiście żadne inne zespoły nie mają takiego poziomu dostępu, więc po zwolnieniu systemu enkapsulacja jest utrzymywana.

 320
Author: Ash,
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-07-31 08:48:17

Jeśli Bob potrzebuje BigImportantClass, to Bob musi dostać ludzi, którzy posiadają projekt a, aby zarejestrować się, aby zagwarantować, że BigImportantClass zostanie napisany w celu zaspokojenia jego potrzeb, przetestowany w celu zapewnienia, że spełnia jego potrzeby, jest udokumentowany jako spełniający jego potrzeby, i że proces zostanie wprowadzony w celu zapewnienia, że nigdy nie zostanie zmieniony tak, aby nie zaspokoić jego potrzeb.

Jeśli klasa jest wewnętrzna, to nie musi przechodzić przez ten proces, co oszczędza budżet dla projektu A, który mogą wydawać na inne rzeczy.

Sens wewnętrzny nie polega na tym, że utrudnia życie Bobowi. Chodzi o to, że pozwala kontrolować to, co drogie obietnice projekt a składa o funkcjach, żywotności, kompatybilności i tak dalej.

 76
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
2010-06-10 16:05:49

Innym powodem użycia internal jest zaciemnianie plików binarnych. Obfuscator wie, że bezpiecznie jest zakodować nazwę klasy jakichkolwiek klas wewnętrznych, podczas gdy nazwy klas publicznych nie mogą być zakodowane, ponieważ mogłoby to złamać istniejące referencje.

 54
Author: Joel Mueller,
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
2008-10-04 03:08:37

Jeśli piszesz bibliotekę DLL, która zawiera mnóstwo złożonych funkcji w prostym publicznym API, wtedy" internal " jest używany na elementach klasy, które nie mają być publicznie ujawnione.

Ukrywanie złożoności (znana również jako enkapsulacja) jest główną koncepcją inżynierii oprogramowania wysokiej jakości.

 23
Author: Jeffrey L Whitledge,
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
2008-10-03 13:19:27

Wewnętrzne słowo kluczowe jest często używane podczas budowania owijki na niezarządzanym kodzie.

Gdy masz bibliotekę opartą na C / C++, którą chcesz zaimportować, możesz zaimportować te funkcje jako statyczne funkcje klasy i uczynić je wewnętrznymi, więc twój użytkownik ma dostęp tylko do twojego wrappera, a nie do oryginalnego API, więc nie może z niczym zadzierać. Funkcje statyczne można używać wszędzie w złożeniu, dla wielu klas owijania, których potrzebujesz.

Możesz spójrz na Mono.Cairo, to owijka wokół biblioteki kairskiej, która używa tego podejścia.

 19
Author: Edwin Jarvis,
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
2008-10-04 18:21:42

Kierując się zasadą "używaj tak ścisłego modyfikatora, jak możesz" używam wewnętrznej wszędzie tam, gdzie muszę uzyskać dostęp, powiedzmy, do metody z innej klasy, dopóki nie będę musiał uzyskać dostępu do niej z innego zestawu.

Ponieważ interfejs assembly jest zwykle węższy niż suma jego klas interfaces, jest sporo miejsc, w których go używam.

 11
Author: Ilya Komakhin,
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
2008-10-03 10:51:38

Uważam, że wewnętrzne są znacznie nadużywane. naprawdę nie powinieneś wystawiać pewnych funkcji tylko na określone klasy, których nie chciałbyś na innych konsumentów.

To moim zdaniem łamie interfejs, łamie abstrakcję. Nie oznacza to, że nigdy nie powinien być używany, ale lepszym rozwiązaniem jest refakturowanie do innej klasy lub użycie w inny sposób, jeśli to możliwe. Jednak nie zawsze jest to możliwe.

Powodem może powodować problemy jest to, że inny deweloper może być oskarżony o zbudowanie innej klasy w tym samym zgromadzeniu, co twoja. Posiadanie wewnętrznych elementów zmniejsza klarowność abstrakcji i może powodować problemy w przypadku niewłaściwego użycia. To byłby ten sam problem, jakbyś go upublicznił. Druga klasa, która jest budowana przez innego dewelopera, jest nadal konsumentem, podobnie jak każda klasa zewnętrzna. Abstrakcja I enkapsulacja klas nie służy tylko do ochrony / przed zewnętrznymi klasami, ale dla dowolnych i wszystkich klas.

Kolejnym problemem jest to, że dużo deweloperzy będą myśleć mogą potrzebować użyć go w innym miejscu w montażu i oznaczyć go jako wewnętrzny tak czy inaczej, nawet jeśli nie potrzebują go w tym czasie. Inny deweloper może wtedy pomyśleć, że jest do wzięcia. Zazwyczaj chcesz oznaczyć prywatne, dopóki nie masz zdefiniowanej potrzeby.

Ale niektóre z nich mogą być subiektywne i nie mówię, że nigdy nie powinny być używane. Po prostu używaj w razie potrzeby.

 9
Author: mattlant,
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
2008-10-03 05:03:24

Widziałem kiedyś coś ciekawego, może tydzień, na blogu, którego nie pamiętam. Zasadniczo nie mogę wziąć kredyt za to, ale pomyślałem, że może to mieć jakąś użyteczną aplikację.

Powiedzmy, że chciałeś, aby klasa abstrakcyjna była widziana przez inne Zgromadzenie, ale nie chcesz, aby ktoś mógł ją odziedziczyć. Sealed nie zadziała, ponieważ jest abstrakcyjny z jakiegoś powodu, inne klasy w tym zbiorze dziedziczą po nim. Prywatny nie zadziała, bo możesz chcieć zadeklarować klasę rodzica gdzieś w innym zgromadzeniu.

namespace Base.Assembly
{
  public abstract class Parent
  {
    internal abstract void SomeMethod();
  }

  //This works just fine since it's in the same assembly.
  public class ChildWithin : Parent
  {
    internal override void SomeMethod()
    {
    }
  }
}

namespace Another.Assembly
{
  //Kaboom, because you can't override an internal method
  public class ChildOutside : Parent
  {
  }

  public class Test 
  { 

    //Just fine
    private Parent _parent;

    public Test()
    {
      //Still fine
      _parent = new ChildWithin();
    }
  }
}

Jak widzisz, efektywnie pozwala komuś używać klasy rodzica bez możliwości dziedziczenia.

 8
Author: Programmin Tool,
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
2008-10-03 13:12:14

Ten przykład zawiera dwa pliki: Assembly1.cs i Assembly2.cs. Pierwszy plik zawiera wewnętrzną klasę bazową, BaseClass. W drugim pliku próba utworzenia instancji BaseClass spowoduje błąd.

// Assembly1.cs
// compile with: /target:library
internal class BaseClass 
{
   public static int intM = 0;
}

// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess 
{
   static void Main()
   {  
      BaseClass myBase = new BaseClass();   // CS0122
   }
}

W tym przykładzie użyj tych samych plików, których użyłeś w przykładzie 1, i zmień poziom dostępności BaseClass na public . Zmień również poziom dostępności pręta IntM na wewnętrzny . W takim przypadku możesz utworzyć instancję klasy, ale nie możesz dostęp do wewnętrznego członka.

// Assembly2.cs
// compile with: /target:library
public class BaseClass 
{
   internal static int intM = 0;
}

// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess 
{
   static void Main() 
   {      
      BaseClass myBase = new BaseClass();   // Ok.
      BaseClass.intM = 444;    // CS0117
   }
}

Źródło: http://msdn.microsoft.com/en-us/library/7c5ka91b (VS. 80). aspx

 7
Author: Murad Mohd Zain,
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
2011-04-14 16:18:56

Bardzo ciekawym zastosowaniem internal - z wewnętrznym członem oczywiście ograniczonym tylko do zespołu, w którym jest zadeklarowany - jest uzyskanie funkcjonalności "friend"w pewnym stopniu z niego. Członek przyjaciel jest czymś, co jest widoczne tylko dla niektórych innych zgromadzeń poza zgromadzeniem, w którym jego zadeklarowane. C# nie ma wbudowanego wsparcia dla friend, jednak CLR tak.

Możesz użyć InternalsVisibleToAttribute aby zadeklarować zespół znajomego, a wszystkie odniesienia z w ramach friend assembly będzie traktować wewnętrznych członków twojego zgromadzenia deklarującego jako publicznych w ramach friend assembly. Problem z tym polega na tym, że wszyscy członkowie wewnętrzni są widoczni; nie możesz wybierać i wybierać.

Dobrym zastosowaniem dla InternalsVisibleTo jest wystawianie różnych wewnętrznych członków na jednostkowy zespół testowy, eliminując w ten sposób potrzebę skomplikowanych prac refleksyjnych do testowania tych członków. Widoczność wszystkich członków wewnętrznych nie stanowi jednak większego problemu takie podejście dość mocno psuje interfejsy klas i może potencjalnie zrujnować enkapsulację w zestawie deklarującym.

 6
Author: cfeduke,
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
2008-10-03 11:39:05

Gdy masz metody, klasy itp., które muszą być dostępne w ramach bieżącego zestawu, a nigdy poza nim.

Na przykład, DAL może mieć ORM, ale obiekty nie powinny być narażone na warstwę biznesową wszystkie interakcje powinny być wykonywane metodami statycznymi i przekazywane w wymaganych parametrach.

 5
Author: Aaron Powell,
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
2008-10-03 04:52:57

Redukcja Szumów, im mniej typów wystawiasz, tym prostsza jest Twoja biblioteka. Zabezpieczenie przed manipulacją to inna sprawa (chociaż odbicie może z nią wygrać).

 4
Author: Quibblesome,
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
2008-10-03 11:02:13

Jako zasada-of-thumb istnieją dwa rodzaje członków:

  • Powierzchnia Publiczna : widoczna z zewnętrznego zespołu (publicznego, chronionego i wewnętrznego chronionego): wywołujący nie jest zaufany, więc Walidacja parametrów, dokumentacja metody itp. jest potrzebny.
  • private surface : niewidoczne z zewnętrznego zespołu (prywatne i wewnętrzne, lub wewnętrzne klasy): wywołujący jest na ogół zaufany, więc Walidacja parametrów, dokumentacja metody itp. można pominąć.
 4
Author: Michael Damatov,
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-04-25 18:43:54

Wewnętrzne klasy pozwalają ograniczyć API Twojego zestawu. Ma to swoje zalety, takie jak ułatwienie zrozumienia interfejsu API.

Ponadto, jeśli błąd istnieje w twoim zestawie, jest mniejsza szansa na poprawkę wprowadzającą zmianę łamiącą. Bez klas wewnętrznych, trzeba by założyć, że zmiana członków publicznych dowolnej klasy byłaby przełomową zmianą. Z klasami wewnętrznymi, można założyć, że modyfikowanie ich publicznych członków łamie tylko wewnętrzne API zgromadzenia (i wszystkie zespoły odwołujące się do atrybutu InternalsVisibleTo).

Lubię enkapsulację na poziomie klasy i na poziomie montażu. Są tacy, którzy się z tym nie zgadzają, ale miło jest wiedzieć, że funkcjonalność jest dostępna.

 3
Author: Sam Pearson,
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
2010-06-10 16:17:51

Mam projekt, który używa LINQ-to-SQL do back-endu danych. Mam dwie główne przestrzenie nazw: Biz i Data. Model danych LINQ żyje w danych i jest oznaczony jako "wewnętrzny"; Przestrzeń nazw Biz ma publiczne klasy, które owijają się wokół klas danych LINQ.

Jest więc Data.Client i Biz.Client; ten ostatni ujawnia wszystkie istotne właściwości obiektu danych, np.:

private Data.Client _client;
public int Id { get { return _client.Id; } set { _client.Id = value; } }

Obiekty Biz mają prywatny konstruktor (wymuszający użycie metod fabrycznych) i wewnętrzny konstruktor, który wygląda tak:

internal Client(Data.Client client) {
    this._client = client;
}

, które mogą być używane przez dowolną klasę biznesową w bibliotece, ale front-end (UI) nie ma możliwości bezpośredniego dostępu do modelu danych, zapewniając, że warstwa biznesowa zawsze działa jako pośrednik.

To pierwszy raz, kiedy naprawdę używam internal dużo, i okazuje się całkiem przydatny.

 2
Author: Keith Williams,
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
2008-10-03 12:52:08

Są przypadki, kiedy sensowne jest tworzenie członków klas internal. Jednym z przykładów może być, jeśli chcesz kontrolować sposób tworzenia instancji klas; powiedzmy, że dostarczasz jakąś fabrykę do tworzenia instancji klasy. Można utworzyć konstruktor internal, tak aby fabryka (która znajduje się w tym samym złożeniu) mogła tworzyć instancje klasy, ale kod spoza tego złożenia nie może.

Jednak nie widzę sensu tworzenia klas lub członków {[0] } bez konkretnych powody, tak mało, jak to ma sens, aby je public, lub {[4] } bez konkretnych powodów.

 2
Author: Fredrik Mörk,
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
2010-06-10 16:01:59

Jedyną rzeczą, na której użyłem wewnętrznego słowa kluczowego, jest kod sprawdzający licencję w moim produkcie; -)

 1
Author: Steven A. Lowe,
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
2008-10-03 05:32:13

Jednym z zastosowań wewnętrznego słowa kluczowego jest ograniczenie dostępu do konkretnych implementacji od użytkownika Twojego zestawu.

Jeśli masz fabrykę lub inną centralną lokalizację do konstruowania obiektów, użytkownik Twojego zestawu musi zajmować się tylko publicznym interfejsem lub abstrakcyjną klasą bazową.

Również wewnętrzne konstruktory pozwalają kontrolować, gdzie i kiedy jest tworzona instancja klasy publicznej.

 1
Author: Andrew Kennan,
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
2008-10-03 05:37:46

Co powiesz na ten: zazwyczaj zaleca się, aby nie ujawniać obiektu listy zewnętrznym użytkownikom zestawu, a raczej eksponować liczbę. Dużo łatwiej jest jednak użyć obiektu List wewnątrz złożenia, ponieważ otrzymujemy składnię array i wszystkie inne metody List. Tak więc zazwyczaj mam wewnętrzną właściwość, która ujawnia listę do użycia wewnątrz zespołu.

Komentarze są mile widziane na temat tego podejścia.

 1
Author: Samik R,
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
2009-12-30 19:18:14

Pamiętaj, że każda klasa zdefiniowana jako public automatycznie pojawi się w intellisense, gdy ktoś spojrzy na Twoją przestrzeń nazw projektu. Z punktu widzenia API ważne jest, aby pokazywać użytkownikom projektu tylko te klasy, z których mogą korzystać. Użyj słowa kluczowego internal, aby ukryć rzeczy, których nie powinni widzieć.

Jeśli Twój Big_Important_Class For Project A jest przeznaczony do użytku poza twoim projektem, nie powinieneś go oznaczyć internal.

Jednak w wielu projektach często będziesz miał zajęcia, które są naprawdę przeznaczone tylko do użytku wewnątrz projektu. Na przykład, możesz mieć klasę, która przechowuje argumenty do sparametryzowanego wywołania wątku. W takich przypadkach, należy oznaczyć je jako internal, jeśli nie z innego powodu niż chronić się przed niezamierzoną zmianą API w drodze.

 1
Author: Matt Davis,
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
2010-06-10 16:04:34

Chodzi o to, że kiedy projektujesz bibliotekę, tylko klasy, które są przeznaczone do użytku z zewnątrz (przez klientów Twojej biblioteki) powinny być publiczne. W ten sposób możesz ukryć klasy, które

  1. mogą ulec zmianie w przyszłych wydaniach (gdyby były publiczne, złamałbyś kod klienta)
  2. są bezużyteczne dla klienta i mogą powodować zamieszanie
  3. nie są bezpieczne (więc niewłaściwe użycie może poważnie uszkodzić bibliotekę)

Itd.

Jeśli rozwijasz wewnętrzne rozwiązania niż wykorzystanie elementów wewnętrznych nie są chyba aż tak ważne, ponieważ zazwyczaj klienci będą mieli stały kontakt z Tobą i / lub dostęp do kodu. Są one jednak dość krytyczne dla twórców bibliotek.

 0
Author: Grzenio,
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
2010-06-10 16:06:53

Kiedy masz klasy lub metody, które nie pasują do paradygmatu zorientowanego obiektowo, które robią niebezpieczne rzeczy, które muszą być wywoływane z innych klas i metod pod twoją kontrolą, i których nie chcesz pozwolić nikomu innemu używać.

public class DangerousClass {
    public void SafeMethod() { }
    internal void UpdateGlobalStateInSomeBizarreWay() { }
}
 -6
Author: yfeldblum,
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
2008-10-03 04:49:17