Vra

Kan jy asseblief verduidelik wat die praktiese gebruik is vir die internal navraag in C#?

Ek weet dat die internal wysiger grense toegang tot die huidige vergadering, maar wanneer en in watter omstandighede moet ek dit gebruik?

Was dit nuttig?

Oplossing

Nut of helper klasse/metodes wat jy wil om toegang te verkry van baie ander klasse in dieselfde vergadering, maar wat jy wil om te verseker dat die kode in ander gemeentes kan nie toegang tot.

Uit MSDN (via archive.org):

'n algemene gebruik van interne toegang is in die komponent-gebaseerde ontwikkeling omdat dit in staat stel om'n groep van die komponente om saam te werk in'n private wyse, sonder om blootgestel aan die res van die program kode.Byvoorbeeld, 'n raamwerk vir die bou van grafiese gebruikerkoppelvlakke kon voorsien Beheer en Vorm klasse wat saam met lede met interne toegang.Aangesien hierdie lede is interne, hulle is nie blootgestel aan die kode wat is die gebruik van die raamwerk.

Jy kan ook gebruik om die interne wysiger saam met die InternalsVisibleTo vergadering vlak kenmerk te skep "vriend" gemeentes wat toegestaan spesiale toegang tot die teiken vergadering interne klasse.

Dit kan nuttig wees vir die skepping van eenheid toets gemeentes wat word dan toegelaat om te bel interne lede van die vergadering om getoets te word.Natuurlik geen ander gemeentes toegestaan hierdie vlak van toegang, so wanneer jy vrystelling van jou stelsel, inkapseling gehandhaaf word.

Ander wenke

As Bob moet BigImportantClass dan Bob moet die mense wat eie projek A kry om aan te meld om te verseker dat BigImportantClass sal geskryf word om sy behoeftes te voorsien, getoets om te verseker dat dit voldoen aan sy behoeftes, is gedokumenteer as die vergadering van sy behoeftes, en dat 'n proses in plek gestel sal word om te verseker dat dit nooit sal verander word sodat dit nie meer voldoen aan sy behoeftes.

As 'n klas is interne dan is dit nie hoef te gaan deur middel van die proses, wat begroting spaar vir Projek A wat hulle kan spandeer op ander dinge.

Die punt van interne is nie dat dit maak die lewe moeilik vir Bob. Dit is wat dit laat jou toe om te beheer wat duur beloftes Projek A maak oor funksies, leeftyd, verenigbaarheid, en so aan.

Nog 'n rede interne gebruik is as jy jou binaries verduisteren. Die Obfuscator weet dat dit veilig is om die klas se naam enige interne klasse klouter, terwyl die naam van openbare klasse nie kan roer, want dit bestaande verwysings kan breek.

As jy 'n DLL wat 'n ton van komplekse funksies saamvat in 'n eenvoudige openbare API skryf, dan "interne" gebruik word op die klas lede wat nie in die openbaar blootgestel word.

Die wegsteek van kompleksiteit (ook bekend as inkapseling) is die hoof konsep van kwaliteit sagteware-ingenieurswese.

Die interne navraag is swaar gebruik wanneer jy die bou van 'n wrapper oor non-bestuur-kode.

As jy 'n C / C ++ gebaseer biblioteek wat jy wil DllImport jy kan hierdie funksies as statiese funksies van 'n klas in te voer, en maak hulle interne, sodat jou gebruikers net toegang tot jou wrapper en nie die oorspronklike API so dit kan nie gemors met enigiets. Die funksies om statiese jy kan hulle oral gebruik in die gemeente, vir die verskeie wrapper klasse wat jy nodig het.

Jy kan 'n blik op Mono.Cairo neem, is dit 'n wrapper rondom Kaïro biblioteek wat hierdie benadering gebruik.

gedryf deur "gebruik as 'n streng wysiger as jy kan" reël ek gebruik interne oral waar ek nodig het om toegang te verkry, sê, metode van 'n ander klas totdat ek uitdruklik nodig om dit te bekom van 'n ander gemeente.

As gemeente koppelvlak is gewoonlik meer smal as som van sy klasse koppelvlakke, daar is nogal baie plekke waar ek dit gebruik.

Ek vind interne ver veelvuldig te wees. jy moet regtig nie seker functionailty word bloot net om sekere klasse wat jy wil nie om ander verbruikers.

Dit in my opinie breek die koppelvlak, breek die onttrekking. Dit is nie te sê dit moet nooit gebruik word nie, maar 'n beter oplossing is om refactor na 'n ander klas of om gebruik te word in 'n ander manier as moontlik. Maar dit kan nie altyd moontlik wees.

Die redes dit kan probleme veroorsaak, is dat 'n ander ontwikkelaar mag gehef word met die bou van 'n ander klas in dieselfde vergadering wat joune is. Met internals verminder die helderheid van die onttrekking, en kan probleme veroorsaak as misbruik. Dit sou dieselfde probleem wees asof jy dit openbaar gemaak. Die ander klas wat gebou word deur die ander ontwikkelaar is nog 'n verbruiker, net soos enige eksterne klas. Klas onttrekking en inkapseling isnt net vir beskerming vir / van eksterne klasse, maar vir enige en alle klasse.

Nog 'n probleem is dat baie van die ontwikkelaars sal dink hulle mag nodig wees om dit elders te gebruik in die vergadering en merk dit as interne anyways, selfs al is hulle nie nodig het dit op die oomblik. Nog 'n ontwikkelaar kan dan sy daar dink vir die neem. Tipies jy wil merk private totdat jy 'n definative behoefte.

Maar sommige van hierdie kan subjektief wees, en Ek sê nie dit moet nooit gebruik word. gebruik net wanneer dit nodig is.

het 'n interessante een die ander dag, miskien week, op 'n blog dat ek nie kan onthou nie. Basies kan ek nie krediet vir hierdie, maar ek het gedink dit is dalk 'n nuttige toepassing het.

Sê jy wou 'n abstrakte klas om gesien te word deur 'n ander gemeente, maar jy wil nie iemand om in staat wees om te erf uit dit. Verseël sal nie werk nie, want dit is abstrakte vir 'n rede, ander klasse in daardie vergadering nie in besit van dit. Private sal nie werk nie, want jy dalk wil om iewers te verklaar 'n Ouer klas in die ander gemeente.

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();
    }
  }
}

Soos jy kan sien, is dit effektief kan iemand aan die Ouer klas gebruik sonder om erf.

Hierdie voorbeeld bevat twee lêers: Assembly1.cs en Assembly2.cs. Die eerste lêer bevat 'n interne basis klas, BaseClass. In die tweede lêer, sal 'n poging om BaseClass instansieer 'n fout maak.

// 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
   }
}

In hierdie voorbeeld, gebruik dieselfde lêers wat jy gebruik in voorbeeld 1, en verander die toeganklikheid vlak van BaseClass om openbare . Ook verander die toeganklikheid vlak van die lid IntM om interne . In hierdie geval, kan jy die klas instansieer, maar jy kan nie toegang tot die interne lid.

// 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
   }
}

bron : http: //msdn.microsoft.com/en-us/library/7c5ka91b(VS.80).aspx

'n Baie interessante gebruik van interne - met interne lid van die kursus word slegs beperk tot die gemeente in waarin verklaar word - is steeds 'n "vriend" funksie tot 'n mate daaruit. 'N Vriendin lid is iets wat slegs sigbaar is aan sekere ander gemeentes buite die gemeente waarin sy verklaar. C # is geen ingeboude ondersteuning vir vriend, maar die CLR doen.

Jy kan gebruik InternalsVisibleToAttribute om verklaar 'n vriend vergadering, en alle verwysings vanuit die vriend vergadering sal binne die bestek van die vriend vergadering behandel die interne lede van jou verklaar vergadering as openbare. 'N Probleem met hierdie is dat alle interne lede sigbaar; jy kan nie kies en keur.

'n goeie gebruik vir InternalsVisibleTo is om verskeie interne lede bloot te stel aan 'n eenheid toets vergadering dus die uitskakeling van die behoefte vir 'n komplekse weerspieëling werk arounds om dié lede te toets. Alle interne lede om sigbaar is nie so veel van 'n probleem, maar die neem van hierdie benadering nie muck jou klas koppelvlakke mooi swaar en kan potensieel ruïneer inkapseling binne die verklaring vergadering.

As jy 'metodes, klasse, ens wat nodig toeganklik wees binne die bestek van die huidige vergadering en nooit buite dit.

Byvoorbeeld, 'n DAL mag 'n ORM het maar die voorwerpe moet nie blootgestel word aan die besigheid laag al interaksie moet gedoen word deur statiese metodes en verby in die vereiste paramters.

As reël-van-duim is daar twee soorte lede:

  • openbare oppervlak : sigbaar is vanaf 'n eksterne vergadering (openbare, beskerm, en interne beskerm): oproeper is nie vertrou het, so parameter validering, metode dokumentasie, ens is nodig.
  • private oppervlak : nie sigbaar is vanaf 'n eksterne vergadering (private en interne of interne klasse): oproeper is oor die algemeen vertrou, so parameter validering, metode dokumentasie, ens kan weggelaat word.

Geraas vermindering, die minder tipes jy die meer eenvoudige jou biblioteek is bloot. Peuter bestendigheid / Security is 'n ander (hoewel Refleksie kan wen daarteen).

Interne klasse in staat stel om die API van jou gemeente te beperk. Dit het voordele, soos die maak van jou API makliker om te verstaan.

Ook, as 'n fout in jou gemeente bestaan, is daar minder van 'n kans om die fix bekendstelling van 'n verbreking verandering. Sonder interne klasse, sal jy het om te aanvaar dat die verandering van openbare lede enige klas se verbreking verandering sal wees. Met interne klasse, kan jy aanvaar dat die wysiging van hul openbare lede net breek die interne API van die vergadering (en enige gemeentes waarna verwys word in die InternalsVisibleTo kenmerk).

Ek hou daarvan om inkapseling by die klas vlak en by die vergadering vlak. Daar is 'n paar wat nie saamstem met hierdie, maar dit is lekker om te weet dat die funksie is beskikbaar.

Ek het 'n projek wat LINQ-tot-SQL gebruik vir die data back-end. Ek het twee hoof naamruimtes: Biz en Data. Die LINQ data model woon in Data en gemerk "interne"; die Biz naamruimte het openbare klasse wat wrap rondom die LINQ data klasse.

Daar is dus Data.Client, en Biz.Client; laasgenoemde ontbloot alle relevante eienskappe van die data voorwerp, Bv:.

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

Die Biz voorwerpe het 'n private konstruktor (om die gebruik van die fabriek metodes dwing), en 'n interne konstruktor wat lyk soos volg:

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

Dit kan gebruik word deur enige van die sake-klasse in die biblioteek, maar die front-end (UI) het geen manier om direk toegang tot die data model, om te verseker dat die besigheid laag altyd tree op as 'n tussenganger.

Dit is die eerste keer dat ek regtig baie gebruik internal, en dit is bewys baie nuttig.

Daar is gevalle wanneer dit sinvol om lede van klasse internal maak. Een voorbeeld kan wees as jy wil om te beheer hoe die klasse word aangehaal; kom ons sê jy gee 'n soort van die fabriek vir die skep van gevalle van die klas. Jy kan die konstruktor internal maak, sodat die fabriek (wat woonagtig is in dieselfde gemeente) gevalle van die klas kan skep, maar code buite daardie gemeente kan nie.

Maar ek kan nie enige punt sien met die maak van klasse of lede internal sonder spesifieke redes, net so min as dit sin maak om hulle public, of private sonder spesifieke redes maak.

Die enigste ding wat ek nog ooit die interne navraag gebruik op die-lisensie nagaan kode in my produk; -)

Een gebruik van die interne navraag is om toegang tot konkrete implementering beperk van die gebruiker van jou gemeente.

As jy 'n fabriek of 'n ander sentrale plek vir die bou van voorwerpe die gebruiker van jou vergadering hoef net te gaan met die openbare koppelvlak of abstrakte basis klas.

Ook, interne vervaardigerskampioenskap toelaat om beheer oor waar en wanneer 'n andersins openbare klas is aangehaal.

Hoe gaan dit met hierdie een: tipies dit word aanbeveel dat jy nie 'n Lys voorwerp bloot te stel aan eksterne gebruikers van 'n vergadering, eerder bloot 'n IEnumerable. Maar dit is baie makliker om 'n Lys voorwerp gebruik binne die gemeente, omdat jy die skikking sintaksis, en alle ander List metodes kry. So, ek het gewoonlik 'n interne eiendom bloot 'n lys te gebruik binne die gemeente.

Kommentaar is welkom oor hierdie benadering.

Hou in gedagte dat enige klas gedefinieer as public outomaties sal wys in die IntelliSense wanneer iemand kyk na jou projek naamruimte. Van 'n API perspektief, is dit belangrik om net show gebruikers van jou projek die klasse wat hulle kan gebruik. Gebruik die internal navraag aan dinge wat hulle nie moet sien om weg te steek.

As u Big_Important_Class vir Projek A is bedoel vir gebruik buite jou projek, dan moet jy nie merk dit internal.

Maar in baie projekte, sal jy dikwels klasse wat eintlik net bedoel is vir gebruik in 'n projek. Byvoorbeeld, kan jy 'n klas wat die argumente hou om 'n parameters draad aanroeping het. In sulke gevalle, moet jy hulle merk as internal as vir geen ander rede as om jouself te beskerm teen 'n onbedoelde API verandering in die pad af.

Die idee is dat as jy die ontwerp van 'n biblioteek net die klasse wat bedoel is vir gebruik van buite (deur kliënte van jou biblioteek) publiek moet wees. Op hierdie manier kan jy klasse weg te steek dat

  1. Is geneig om te verander in toekomstige uitgawes (as hulle openbare u kliënt kode te breek)
  2. Is nutteloos om die kliënt en kan verwarring veroorsaak
  3. Is nie veilig (so onbehoorlike gebruik kan jou biblioteek te breek mooi sleg)

ens.

As jy die ontwikkeling van inhouse oplossings as die gebruik van interne elemente is nie so belangrik ek dink, want gewoonlik die kliënte konstante kontak met jou en / of toegang tot die kode sal hê. Hulle is redelik krities vir biblioteek ontwikkelaars al is.

As jy klasse of metodes wat nie skoon nie inpas in die objekgeoriënteerde paradigma wat gevaarlike dinge doen, wat nodig het om te noem van ander klasse en metodes onder jou beheer, en wat jy nie wil hê om jou te laat enigiemand anders gebruik.

public class DangerousClass {
    public void SafeMethod() { }
    internal void UpdateGlobalStateInSomeBizarreWay() { }
}
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top