C # Metode de extensie Arhitectura Întrebare




Am întrebat recent această întrebare:
 [compilatorul eroare corelarea C Metoda # extensie personalizată](https://stackoverflow.com/questions/638463)


Marc Gravell răspuns a fost perfect și a rezolvat problema mea. Dar mi-a dat ceva să se gândească la ...


Dacă și metoda de prelungire trebuie să fie plasat pe o clasa statică și metoda în sine trebuie să fie static, de ce nu putem crea o metodă de extensie statică?


Am înțeles că parametrul marcat ca fiind „acest lucru“ va fi folosit pentru a permite accesul la o instanță a obiectului extindem. Ceea ce nu înțeleg este de ce nu poate fi o metodă creată pentru a fi statice ... se pare că doar pentru mine că aceasta este o limitare lipsită de sens ...


Întrebarea mea este: De ce nu putem crea o metodă de extensie care va funcționa ca o metodă statică?
Mă aștept răspunsul real este pur și simplu: nu a fost un bun exemplu de utilizare. Pentru cazuri, avantajul este acela că permite o fluente API asupra tipurilor existente (care nu se furnizează logica) - și anume



```
var foo = data.Where(x=>x.IsActive).OrderBy(x=>x.Price).First();

```

care permite LINQ:



```
var foo = (from x in data
           where x.IsActive
           order by x.Price
           select x).First();

```

Cu metode statice, acest lucru pur și simplu nu este o problemă, astfel încât nu există nici o justificare; doar utiliza metoda statică pe al doilea tip.


Așa cum este, metodele de extensie nu sunt *corect* obiect orientate - ele sunt un abuz pragmatic pentru a face viața mai ușoară în detrimentul purității. Nu a fost nici un motiv pentru a dilua metode statice în același mod.
Nr.


Aici sunt mai multe exemple de ce:


1. Cod șablon este imposibil de a scrie cu excepția caietul de sarcini,


șablon
void f( T k )
{
T x( k );
x.x();
}
Copiile ar putea arunca, parametrul care trece ar putea arunca, și `x()` s-ar putea arunca unele necunoscute excepție.


2. Excepție-caietul de sarcini tind să interzică extensibilitate.


virtual void open() throw( FileNotFound );


ar putea evolua în


virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );


Ai putea chiar scrie ca


arunca( ... )


Primul nu este extensibil, cel de-al doilea este un proiect mult prea ambițios și cel de-al treilea este într-adevăr ceea ce vrei să spui, atunci când scrie funcții virtuale.


3. Cod moștenire


Atunci când scrie cod care se bazează pe o altă bibliotecă, nu't știu ce ar putea face atunci când ceva nu merge oribil greșit.


int lib\_f();


void g() throw( k\_too\_small\_exception )
{
int k = lib\_f();
dacă( k < 0 ) arunca k\_too\_small\_exception();
}


"g" se va termina, când lib\_f()`aruncă. Aceasta este (în cele mai multe cazuri), nu ceea ce vrei cu adevărat.`std::termina()` nu ar trebui să fie numit. Este întotdeauna mai bine să lăsați aplicația accident cu o excepție netratată, de la care puteți prelua un stack trace, decât la tăcere/violent muri.


4. Scrie cod care returnează erori comune și aruncă în ocazii excepționale.


Eroarea e = open( "bla.txt" );
if( e == FileNotFound )
MessageUser( "Fișier bla.txt nu a fost găsit" );
if( e == AccessDenied )
MessageUser( "nu a Reușit să deschidă bla.txt, pentru că nu ne't au citit drepturile ..." );
dacă( e != Succes )
MessageUser( "nu a Reușit din cauza la un alt eroare, codul de eroare = " + itoa( e ) );


încercați
{
std::vector k( 1000 );
// ...
}
a prinde( const bad\_alloc& b )
{
MessageUser( "de memorie, ieșirea procesului de" );
arunca;
}


Cu toate acestea, atunci când bibliotecă doar aruncă-ți de propriile excepții, puteți utiliza excepție caietul de sarcini a stat intenția ta. Știu că acest subiect este vechi, dar această problemă continuă să vină și nu a fost soluționată spre satisfacția mea:


Dacă salvați obiecte în $\_SESSION, sau de a le reconstrui întreaga pânză în baza de date a ascuns în câmpuri de formular ascunse, sau re-interogare-le din DB de fiecare dată, utilizați stat. HTTP este apatrid (mai mult sau mai puțin; dar vezi OBȚINE vs PUS), dar aproape tot ce-i pasă cuiva de-a face cu o aplicație web necesită de stat pentru a fi menținut pe undeva. Acționează ca în cazul în împingând stat în colțuri și crăpături se ridică la un fel de câștig teoretic este pur și simplu greșit. Statul este stat. Dacă utilizați stat, pierzi diverse avantaje tehnice acumulate de apatrid. Acest lucru nu este ceva pentru a dormi, cu excepția cazului în care știți că ar trebui să-și fi pierdut somnul din cauza asta.


Sunt deosebit de afectat de binecuvântarea primită de la "dubla" argumentele prezentate de Hank Gay. Este OP construirea unei distribuite și încărcare echilibrată sistem de e-commerce? Părerea mea este că nu, și nu va mai pleca de la premiza că serializarea lui $clasa de Utilizare, sau orice altceva, nu va infirm serverul lui de dincolo de reparații. Sfatul meu: foloseste tehnici care sunt sensibile la cererea dumneavoastră. Obiecte în $\_SESSION sunt bine, pot să-simț măsuri de precauție. Dacă aplicația se transformă brusc în ceva rivalizând Amazon în trafic servit, va trebui să re-adapteze. Ca's viață. Utilizați de fiecare dată când suprascrie o metodă pentru două beneficii. Fă-l astfel încât să puteți profita de compilatorul de verificare pentru a face sigur că de fapt sunt imperative o metodă atunci când crezi că ești. În acest fel, dacă ați făcut o greșeală comună de greșeli de scriere o metodă numele sau nu se potrivesc în mod corect parametrii, veți fi avertizat că metoda nu suprascrie pe cum crezi. În al doilea rând, ea face codul mai ușor de înțeles, pentru că este mult mai evident atunci când metodele sunt suprascrise.


În plus, în Java 1.6 puteți să-l utilizați pentru a marca atunci când o metodă implementează o interfață pentru aceleași beneficii. Cred că ar fi mai bine să aibă o separa de adnotare (ca `@Implementează`), dar'e mai bine decât nimic. **UPDATE**


Acest răspuns este destul de vechi, și așa descrie ceea ce a fost 'bine' la momentul respectiv, care a fost inteligent indicii furnizate de Impuls bibliotecă. Deoarece C++11, biblioteca standard a furnizat suficiente smart pointeri de tipuri, și așa ar trebui să favorizeze utilizarea [`std::unique_ptr`](http://en.cppreference.com/w/cpp/memory/unique_ptr), [`std::shared_ptr`](http://en.cppreference.com/w/cpp/memory/shared_ptr) și [`std::weak_ptr`](http://en.cppreference.com/w/cpp/memory/weak_ptr). 


Acolo a fost, de asemenea, [`std::auto_ptr`](http://en.cppreference.com/w/cpp/memory/auto_ptr). A fost foarte mult ca o luneta pointer, cu excepția faptului că a avut, de asemenea, "speciale" periculoase capacitatea de a fi copiate — care, de asemenea, în mod neașteptat transferă dreptul de proprietate.
**S-a depreciat în C++11 și eliminate în C++17**, deci nu ar trebui't-l folosească.



```
std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.
```






**RĂSPUNS VECHI**


Un smart pointer este o clasa care se infasoara un 'prime' (sau 'gol') C++ pointer, pentru a gestiona durata de viață a obiectului de a fi subliniat. Nu există nici un singur inteligente de tip pointer, dar toate dintre ele încerca să rezumat o primă pointer într-un mod practic.


Smart pointeri ar trebui să fie de preferat peste prime indicii. Dacă simțiți că aveți nevoie pentru a utiliza pointeri (ia în considerare mai întâi dacă într-adevăr ** face), ar fi normal să doriți să utilizați un smart pointer deoarece acest lucru poate atenua multe dintre problemele cu prime indicii, în principal, uitând să ștergeți obiectul și scurgeri de memorie.


Cu prime indicii, programatorul trebuie să specifice în mod explicit distruge obiectul atunci când acesta nu mai este util.



```
// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?
```

Un smart pointer prin comparație definește o politică ca atunci când obiectul este distrus. Tu încă mai au pentru a crea un obiect, dar nu mai trebuie să vă faceți griji despre distrugerea ei.



```
SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception
```

Cea mai simplă politica de utilizare implică domeniul de aplicare de smart pointer obiect înveliș, cum ar fi puse în aplicare până la [`boost::scoped_ptr`](https://www.boost.org/doc/libs/release/libs/smart_ptr/scoped_ptr.htm) sau [`std::unique_ptr`](http://en.cppreference.com/w/cpp/memory/unique_ptr). 



```
void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}
```

Notă: std::unique\_ptr` cazuri nu pot fi copiate. Acest lucru previne pointer de a fi șterse de mai multe ori (în mod incorect). Cu toate acestea, puteți trece referiri la aceasta în jurul valorii de la alte funcții-ai sunat.


`std::unique\_ptr sunt utile atunci când doriți pentru a lega de viata a obiectului la un anumit bloc de cod, sau dacă încorporat ca date membre în interiorul altui obiect, durata de viata de care alt obiect. Obiectul există până conțin bloc de cod este ieșit, sau până la obiect este distrus.


Mai complex smart pointer politică implică numărare de referință indicatorul. Acest lucru permite ca indicatorul să fie copiate. Când ultima "de referință" la obiectul este distrus, obiectul este șters. Această politică este implementată de [`boost::shared_ptr`](https://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm) și [`std::shared_ptr`](http://en.cppreference.com/w/cpp/memory/shared_ptr).



```
void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.
```

Referință numărat indicii sunt foarte utile atunci când durata de viață a obiectului este mult mai complicat, și nu este legat direct la o anumită secțiune de cod sau de la un alt obiect.


Există un dezavantaj de referință numărat pointer — posibilitatea de a crea o marionetă de referință:



```
// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!
```

O altă posibilitate este crearea de referințe circulare:



```
struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!
```

Pentru a rezolva această problemă, atât Stimula și C++11 au definit o `weak_ptr` pentru a defini un slab (nenumărate) de referință la un `shared_ptr`. În afară de diferența aparentă de 


* având de a declara valoarea in timp de o definiție pentru un `const` VS `readonly` valori pot fi calculate dinamic, dar trebuie să fie atribuite înainte de constructorul ieșirile.. după care este înghețat.
* 'const's sunt implicit "statice". Utilizați o `ClassName.ConstantName` notație pentru a le accesa.


Există o diferență subtilă. Ia în considerare o clasă definită în `AssemblyA`.



```
public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}
```

`AssemblyB "referințe" AssemblyA și folosește aceste valori în cod. Atunci când acest lucru este compilat, 


* în caz de `const` valoare, este ca o găsi-o înlocuiască, valoarea 2 este 'coapte în' la `AssemblyB`'s II. Acest lucru înseamnă că, dacă mâine am'll update `I_CONST_VALUE` 20 în viitor. *`AssemblyB` ar avea încă 2 până am recompilați ea*.
* în caz de `readonly` valoare, este ca un `ref` la o locație de memorie. Valoarea nu este coaptă în `AssemblyB`'s II. Acest lucru înseamnă că, dacă o locație de memorie este actualizat, `AssemblyB` devine noua valoare fără recompilarea. Deci, daca `I_RO_VALUE` este actualizat la 30, ai nevoie doar de a construi AssemblyA`. Toți clienții nu trebuie să fie recompilat.


Deci, dacă sunteți siguri că valoarea constantă a câștigat't schimba folosi un `const`. 



```
public const int CM_IN_A_METER = 100;
```

Dar, dacă aveți o constantă care se poate schimba (de exemplu, w.r.t. precizie).. sau atunci când în dubiu, utilizați o `readonly`. 



```
public readonly float PI = 3.14;
```

*Update: Aku are nevoie pentru a obține o mențiune pentru el a subliniat acest lucru în primul rând. De asemenea, am nevoie să conectați unde am învățat asta.. [Eficiente C# - Bill Wagner](https://www.amazon.com/Effective-Specific-Improve-Software-Development/dp/0321245660)* Potrivit [Java](http://www.oracle.com/technetwork/java/effectivejava-136174.html), capitolul 4, pagina 73, ediția a 2-a:



> 
> "sunt multe motive pentru acest lucru: Imuabil clase sunt mai ușor de a
> proiectarea, implementarea, și de a folosi decât mutabil clase. Acestea sunt mai puțin predispuse
> pentru eroare și sunt mai sigure.
> 
> 
> [...]
> 
> 
> "**Imuabil obiecte sunt simple.** Un obiect imuabile poate fi în
> exact un stat, statul în care a fost creat. Dacă vă asigurați-vă că
> că toți constructorii stabili invarianți, atunci este
> garantat că aceste invariante va rămâne valabil pentru toate timpurile, cu
> nici un efort din partea ta.
> 
> 
> [...]
> 
> 
> **Imuabil obiecte sunt în mod inerent thread-safe; ele nu necesită sincronizare.** Ele nu pot fi corupt de mai multe fire
> accesarea lor în același timp. Acest lucru este, de departe, cea mai simplă abordare
> pentru realizarea fir de siguranță. În fapt, nici un fir poate observa orice
> efect de un alt fir de pe un obiect imuabile. Prin urmare,
> **imuabil obiecte pot fi partajate în mod liber**
> 
> 
> [...]
> 
> 
> 


Alte puncte mici din același capitol:



> 
> Nu numai că puteți partaja obiecte imuabile, dar puteți partaja lor interne.
> 
> 
> [...]
> 
> 
> Imuabil obiecte face mari blocuri de constructii pentru alte obiecte, dacă mutabile sau imuabile.
> 
> 
> [...]
> 
> 
> singurul dezavantaj real al imuabil clase este că au nevoie de un obiect separat pentru fiecare valoare distinctă.
> 
> 
> Membrii privați sunt accesibile doar în cadrul clasei definirea ei.


Protejate membrii sunt accesibile în clasa pe care le definește și în clasele care moștenesc de la clasa respectivă.


Edit: Ambele sunt, de asemenea, accesibil de prieteni din clasa lor, iar în cazul protejate de membri, de prietenii lor de clasele derivate.


Edit 2: Utilizați orice are sens în contextul problema ta. Ar trebui să încercați să facă membrii private ori de câte ori poți să reducă cuplare și de a proteja punerea în aplicare a clasei de bază, dar dacă asta's nu este posibil a folosi apoi protejate de membri. Verifica [C++ FAQ](https://isocpp.org/wiki/faq/basics-of-inheritance) pentru o mai bună înțelegere a problemei. [Această întrebare despre protejate variabile](https://stackoverflow.com/questions/37011/protected-member-variables) s-ar putea, de asemenea, de ajutor. va multumim pentru interesul acordat sectiunii noastre de consultanta.
consideram ca primele demersuri care ar trebui initiate sunt cele pentru clarificarea situatiei juridice a imobilului – titlu de proprietate, succesiune, actualizare in registrele publice.
legat de construirea unui spatiu suplimentar (o veranda), cel mai probabil, este necesara obtinerea unei autorizatii de constructie (extindere), pentru ca orice modificare a structurii sau a caracteristicilor esentiale ale imobilului, este supusa autorizarii. pentru a putea intocmi documentatia si a solicita eliberarea autorizatiei, actele de proprietate trebuie sa fie complete si corecte.
sfatul nostru este sa solicitati mai mutle informatii de la primarie, atat legat de situatia curenta a imobilului, cat si de cerintele legale care trebuie indeplinite pentru realizarea lucrarilor de constructie dorite.
un articol pe aceasta tema:
https://www.reformex.ro/extindere-casa/
va dorim mult succes in demersurile viitoare si va mai asteptam oricand veti avea neclaritati cu privire la piata imobiliara. Probabil că ar trebui să înceapă cu un pic de teorie si exemple simple, cum ar fi [mijloc de deplasare algoritmul](http://www.gameprogrammer.com/fractal.html). Ar trebui, de asemenea, să învețe un pic despre [Zgomot Perlin](https://en.wikipedia.org/wiki/Perlin_noise) dacă sunteți interesat în generarea de grafice. Am folosit asta ca să încep cu ultimul meu an de proiect pe generarea de procedură.


[Fractali](https://en.wikipedia.org/wiki/Fractal) sunt strâns legate de generarea de procedură.


[Terragen](https://en.wikipedia.org/wiki/Terragen) și [SpeedTree](https://en.wikipedia.org/wiki/SpeedTree) vă va arăta unele posibilități uimitoare de procedură generație.


Generarea de procedură este o tehnică ce poate fi folosită în orice limbă (acesta este cu siguranta nu se limitează la limbaje procedurale, cum ar fi C, deoarece poate fi folosit în OO limbi, cum ar fi Java, și Logica limbi, cum ar fi Prolog). O bună înțelegere a recursivitate în orice limbă va consolida înțelegerea dumneavoastră de Generație de Procedură.


Ca și pentru 'grav' sau non-joc de codul de procedură generație de tehnici au fost utilizate pentru:


* simula creșterea orașelor, în scopul de a planului de management al traficului
* pentru a simula creșterea vaselor de sânge
* SpeedTree este folosit în filme și arhitectural prezentări Nu o't schimba nimic, atunci când programul se execută. Tot ce's necesare este încărcat la cerere. Deci, chiar dacă aveți că utilizarea declarație, dacă nu folosesc de fapt un tip în care spațiul de nume / de asamblare, asamblarea că utilizarea declarație este corelată a câștigat't fi încărcat.


În principal, se's, doar pentru a curăța de preferințele personale.