Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Jegyzet
Ez a cikk egy funkcióspecifikáció. A specifikáció a funkció tervezési dokumentumaként szolgál. Tartalmazza a specifikáció javasolt módosításait, valamint a funkció tervezése és fejlesztése során szükséges információkat. Ezeket a cikkeket mindaddig közzéteszik, amíg a javasolt specifikációmódosításokat nem véglegesítik, és be nem építik a jelenlegi ECMA-specifikációba.
A szolgáltatás specifikációja és a befejezett implementáció között eltérések lehetnek. Ezeket a különbségeket a vonatkozó nyelvi tervezési értekezlet (LDM) megjegyzései rögzítik.
A funkcióspektusok C# nyelvi szabványba való bevezetésének folyamatáról a specifikációkcímű cikkben olvashat bővebben.
Bajnoki probléma: https://github.com/dotnet/csharplang/issues/3301
Összefoglalás
A javaslat célja, hogy a C# partial metódusok aláírásával kapcsolatos összes korlátozást eltávolítsa. A cél az, hogy kibővítsük azokat a forgatókönyveket, amelyekben ezek a módszerek együttműködhetnek a forrásgenerátorokkal, valamint általánosabb deklarációs űrlapként szolgálnak a C# metódusokhoz.
Lásd még az eredeti részleges metódusok specifikációját (§15.6.9).
Motiváció
A C# korlátozott támogatást nyújt a metódusokat deklarációkra és definíciókra/ implementációkra felosztó fejlesztők számára.
partial class C
{
// The declaration of C.M
partial void M(string message);
}
partial class C
{
// The definition of C.M
partial void M(string message) => Console.WriteLine(message);
}
A partial metódusok egyik viselkedése, hogy ha a definíció hiányzik, a nyelv egyszerűen törli a partial metódusra irányuló hívásokat. Lényegében úgy viselkedik, mint egy [Conditional] metódus hívása, ahol a feltételt hamisnak értékelték.
partial class D
{
partial void M(string message);
void Example()
{
M(GetIt()); // Call to M and GetIt erased at compile time
}
string GetIt() => "Hello World";
}
Ennek a funkciónak az eredeti motivációja a forrásgenerálás volt tervező által generált kód formájában. A felhasználók folyamatosan szerkesztették a létrehozott kódot, mert a generált kód bizonyos aspektusát össze akarták kapcsolni. A Windows Forms indítási folyamatának legfontosabb részei az összetevők inicializálása után.
A létrehozott kód szerkesztése hibalehetőséget okozott, mert minden olyan művelet, amely miatt a tervező újragenerálta a kódot, a felhasználó szerkesztését törölné. A partial metódus funkció enyhíti ezt a feszültséget, mert lehetővé tette a tervezők számára, hogy horgokat bocsátsanak ki partial metódusok formájában.
A tervezők olyan horgokat bocsáthatnak ki, mint partial void OnComponentInit(), és a fejlesztők deklarációkat határozhatnak meg számukra, vagy nem definiálhatják őket. Mindkét esetben, bár a létrehozott kód lefordítható, és a folyamat iránt érdeklődő fejlesztők szükség szerint becsatlakozhatnak.
Ez azt jelenti, hogy a részleges metódusoknak számos korlátozásuk van:
-
voidvisszatérési típussal kell rendelkeznie. - Nem lehetnek
outparaméterek. - Nem rendelkezhet akadálymentességgel (implicit módon
private).
Ezek a korlátozások azért léteznek, mert a nyelvnek képesnek kell lennie kód kibocsátására a hívási hely törlésekor. Feltevén, hogy törölhetők, a private az egyetlen lehetséges hozzáférhetőség, mert a tag nem jeleníthető meg az összeállítási metaadatok között. Ezek a korlátozások arra is szolgálnak, hogy korlátozzák azokat a forgatókönyveket, amelyekben partial metódusok alkalmazhatók.
A javaslat az partial metódusokra vonatkozó összes meglévő korlátozás eltávolítására vonatkozik. Lényegében lehetővé teszi számukra, hogy out paraméterekkel, nem void visszatérési típusokkal vagy bármilyen hozzáférhetőséggel rendelkezzenek. Az ilyen partial deklarációkhoz hozzá kellene adni azt a követelményt, hogy egy definíciónak léteznie kell. Ez azt jelenti, hogy a nyelvnek nem kell figyelembe vennie a híváswebhelyek törlésének hatását.
Ez kiterjesztené azokat a generátorforgatókönyveket, amelyekben partial metódusok is részt vehetnek, és így a forrásgenerátorok funkciójával jól összekapcsolható. Egy regex például a következő mintával határozható meg:
[RegexGenerated("(dog|cat|fish)")]
partial bool IsPetMatch(string input);
Ez lehetővé teszi a fejlesztő számára, hogy egyszerű deklaratív módon válassza a generátorokat, és biztosítja, hogy a generátorok könnyen áttekintsék a forráskódban található egyszerű deklarációk halmazát, így vezérlik a generált kimenetet.
Hasonlítsa össze azzal a nehézséggel, amelyet egy generátor jelentene a kód következő kódrészletének összekapcsolásakor.
var regex = new RegularExpression("(dog|cat|fish)");
if (regex.IsMatch(someInput))
{
}
Mivel a fordító nem teszi lehetővé, hogy a generátorok módosítsák a kódot, amely ezt a mintát összekapcsolja, ez a generátorok számára szinte lehetetlen lenne. A IsMatch implementációban az implementátoroknak reflektálniuk kell, vagy a felhasználókat kell megkérniük arra, hogy változtassák meg a hívási helyeiket egy új metódusra, és a regex átdolgozásával adják át a szöveges literált argumentumként. Elég rendetlen.
Részletes tervezés
A nyelv úgy változik, hogy lehetővé tegye partial metódusok explicit akadálymentességi módosítóval való megjegyzését. Ez azt jelenti, hogy felcímkézhetők private, publicstb.
Ha egy partial metódus explicit akadálymentességi módosítóval rendelkezik, a nyelv megköveteli, hogy a deklarációnak megfelelő definíciója legyen akkor is, ha az akadálymentesség private:
partial class C
{
// Okay because no definition is required here
partial void M1();
// Okay because M2 has a definition
private partial void M2();
// Error: partial method M3 must have a definition
private partial void M3();
}
partial class C
{
private partial void M2() { }
}
Továbbá a nyelv eltávolítja azokat a korlátozásokat, amelyek egy explicit akadálymentességgel rendelkező partial metóduson megjelenhetnek. Az ilyen deklarációk tartalmazhatnak nem érvénytelen visszatérési típusokat, out paramétereket, extern módosító stb. Ezek az aláírások a C# nyelv teljes kifejezőképességével rendelkeznek.
partial class D
{
// Okay
internal partial bool TryParse(string s, out int i);
}
partial class D
{
internal partial bool TryParse(string s, out int i) { ... }
}
Ez kifejezetten lehetővé teszi, hogy partial metódusok részt vegyenek overrides és interface implementációkban:
interface IStudent
{
string GetName();
}
partial class C : IStudent
{
public virtual partial string GetName();
}
partial class C
{
public virtual partial string GetName() => "Jarde";
}
A fordító módosítja a hibát, amely akkor jelenik meg, ha egy partial metódus tartalmaz egy illegális elemet, amely lényegében a következőket mondja:
A(z)
refnem használható egy olyanpartialmetóduson, amely nem rendelkezik kifejezett hozzáférhetőséggel.
Ez segít a fejlesztőknek a megfelelő irányba mutatni a funkció használatakor.
Korlátozások:
-
partialexplicit akadálymentességgel rendelkező deklarációknak definícióval kell rendelkezniük -
partialdeklarációknak és definíció-aláírásoknak minden metódus- és paramétermódosítón meg kell egyeznie. Csak a paraméternevek és az attribútumlisták lehetnek eltérőek (ez nem új, hanem apartialmetódusok meglévő követelménye).
Kérdések
részleges az összes tagnál
Tekintettel arra, hogy bővítjük partial, hogy barátságosabb legyen a forrásgenerátorok számára, akkor azt is ki kell bővítenünk, hogy minden osztálytagon működjön? Lássuk például, hogy képesek lehetünk-e deklarálni partial konstruktorokat, operátorokat stb.
megoldás Az ötlet jó, de a C# 9 ütemezésének ezen a pontján megpróbáljuk elkerülni a szükségtelen funkciók bővülését. Szeretné megoldani a funkció kibővítésével kapcsolatos azonnali problémát, hogy modern forrásgenerátorokkal működjön.
A C# 10 kiadásban figyelembe vesszük a partial más tagok támogatására való kiterjesztését. Valószínűnek tűnik, hogy figyelembe vesszük ezt a bővítményt. Ez továbbra is aktív javaslat, de még nem implementálták.
Használjon absztraktot részleges helyett
Ennek a javaslatnak a lényege annak biztosítása, hogy a deklarációnak megfelelő definíciója /megvalósítása legyen. Figyelembe véve, hogy abstract kell használnunk, mivel ez már egy nyelvi kulcsszó, amely arra kényszeríti a fejlesztőt, hogy gondolkodjon a megvalósításon?
állásfoglalás Erről egészséges vita alakult ki, de végül ellene döntöttek. Igen, a követelmények ismerősek, de a fogalmak jelentősen eltérnek. A fejlesztő könnyen elhiheti, hogy virtuális nyerőgépeket hoz létre, amikor valójában nem így tesz.
C# feature specifications