Strukturálja szét a rekordokat és egyéb típusokat

Tip

Ez a cikk az Alapismeretek szakasz része azon fejlesztők számára, akik már legalább egy programozási nyelvet ismernek, és c#-t tanulnak. Kezdje a mintaegyeztetés áttekintésével , ha a minták újak Önnek.

A dekonstrukció egyetlen műveletben több változóhoz rendeli egy érték egyes részeit – annak összetevőit. A tuple összetevői azok az elemek, amelyek pozíciójuk alapján érhetők el. Egy másik típus a Deconstruct metódus definiálásával elérhetővé teheti az összetevőket. A pozíciórekordok, amelyek konstruktor-szerű paraméterekként deklarálják a tulajdonságaikat, automatikusan kapnak egy Deconstruct metódust.

Tuple-ök dekonstruálása

Tegyük fel, hogy egy metódus városadatokat tartalmazó tuple-t ad vissza. Az egyes összetevőket egyenként olvashatja el:

var cityData = QueryCityData("New York City");
var city = cityData.City;
var population = cityData.Population;
var area = cityData.Area;

A dekonstruálás egy lépésben rendeli hozzá ezeket az összetevőket:

(string city, int population, double area) = QueryCityData("New York City");

Azt is megadhatja, hogy a C# kikövetkeztesse a változótípusokat:

var (city, population, area) = QueryCityData("New York City");

A dekonstruálás kombinálhat meglévő változókat, újonnan deklarált változókat és eldobásokat egyetlen hozzárendelésben:

(city, var population, _) = QueryCityData("New York City");

Válassza ki azt a megfogalmazást, amely a legkönnyebben olvashatóvá teszi a kódot. A zárójelek előtt lévő egyetlen var gyakran a legtisztább kikövetkeztetett forma. Az explicit típusokat és var a zárójeleken belül is keverheti, de ez a forma általában nehezebben átlátható. Ha csak néhány értékre van szüksége, a pozíciók kihagyása helyett használjon discards-okat.

Felesleges értékek figyelmen kívül hagyása diszkárdokkal

Minden előállított értéknek meg kell felelnie a hozzárendelés bal oldalán lévő pozíciónak. Ha nincs szüksége egy vagy több pozícióra, használja a(z) _ elemet eldobásra:

var (_, _, population1960, _, population2010) = QueryPopulationDataForYears(
    "New York City", 1960, 2010);

Itt a tuple visszaadja a város nevét, két évet és két népességi értéket. A dekompozíció csak a populációs értékeket tartja meg, mert a számítás csak ezeket az összetevőket használja.

Felhasználó által definiált típusok dekonstruálása

Egy osztály, szerkezet vagy interfész egy Deconstruct metódus deklarálásával támogatja a dekonstruálást. Minden összetevő out paraméter lesz, amely lehetővé teszi, hogy a metódus értéket rendeljen a hívó változójához anélkül, hogy visszaadná azt. Mivel minden összetevőt egy out paraméteren keresztül ad vissza, maga a metódus a következőt adja vissza: void

public void Deconstruct(out string firstName, out string middleName, out string lastName)
{
    firstName = FirstName;
    middleName = MiddleName;
    lastName = LastName;
}

Ezután közvetlenül bonthat fel egy példányt:

var (firstName, middleName, lastName) = passenger;

Egy típus több Deconstruct túlterhelést is biztosít különböző aritásokkal – a metódus által deklarált paraméterek számával out –, így a hívók kiválaszthatják, hogy hány összetevőt lekérjenek:

public void Deconstruct(out string firstName, out string lastName)
{
    firstName = FirstName;
    lastName = LastName;
}

public void Deconstruct(out string firstName, out string middleName, out string lastName)
{
    firstName = FirstName;
    middleName = MiddleName;
    lastName = LastName;
}

public void Deconstruct(out string firstName, out string lastName, out string city, out string state)
{
    firstName = FirstName;
    lastName = LastName;
    city = City;
    state = State;
}

Két azonos számú out paraméterrel rendelkező túlterhelés nem egyértelmű. A fordító hibát jelent a nem egyértelmű hívás miatt, ezért a túlterheléseket ne csak paramétertípusok szerint, hanem aritás alapján is különböztesse meg.

Az elvetések a felhasználó által definiált visszabontással is működnek. Az elvetésekről általában az Elvetések és az elvetési minta című témakörben olvashat bővebben:

var (firstName, _, city, _) = passenger;

Rekordok visszabontása

Egy pozicionális rekord record vagy record struct a tulajdonságait magán a típusdeklaráción paraméterekként deklarálja, a konstruktorhoz hasonlóan. A fordító generál Önnek egy Deconstruct metódust out, az említett pozícióparamétereknek megfelelő paraméterekkel:

var (city, highTempC, lowTempC) = forecast;

A létrehozott dekonstrukcióban csak a pozícióparaméterek vesznek részt. A rekordban máshol deklarált további tulajdonságok nem lesznek automatikusan hozzáadva.

Bontsd szét a nem saját típusokat

Ha nem tud módosítani egy típust, akkor is támogathatja a dekonstruálást egy bővítménymetódus megírásával – egy statikus metódussal, amely egy Deconstruct metódust ad hozzá egy nem saját típushoz, mintha az az adott típus tagja lenne. A metódus hozzáadása után bármely Uri érték használhat dekonstruálási szintaxist:

static class UriExtensions
{
    public static void Deconstruct(this Uri uri, out string scheme, out string host, out int port)
    {
        scheme = uri.Scheme;
        host = uri.Host;
        port = uri.Port;
    }
}

Ugyanez a kétértelműségi szabály érvényes itt: két azonos aritású kiterjesztési Deconstruct módszer nem egyértelmű. Kétértelműség is felmerülhet egy példánymetódus Deconstruct és egy azonos számú paraméterrel rendelkező bővítménymetódus között. A fordító mindkét esetben hibát jelez a nem egyértelmű hívás miatt.

Beépített szétszerelés rendszertípusok esetén

Egyes rendszertípusok már definiálnak egy Deconstruct metódust, ugyanazzal a mechanizmussal, amelyet a saját típusaidhoz is használnál. Például támogatja a dekonstruálást, amely tömörré teszi a szótár iterálását:

foreach (var (repo, commitCount) in repoCommitCounts)
{
    Console.WriteLine($"{repo} had {commitCount:N0} commits in this snapshot.");
}

Dekonstruálás és mintailesztés

Az Deconstruct metódus lehetővé teszi az adott típus pozicionális mintáit is. A pozícióminta egy lépésben tesztel és dekonstruál egy értéket, ugyanazzal a zárójeles szintaxissal, mint a dekonstruálás: person is ("Alice", 30) illeszkedik egy Person értékre, amelynek dekonstruált összetevői megegyeznek ezekkel az értékekkel. Ez eltér egy tulajdonságmintától, amely közvetlenül teszteli az elnevezett tulajdonságokat, például person is { Name: "Alice", Age: 30 }. A tulajdonságminták általában világosabbak az objektumstruktúrák esetében, mivel a tagnevek egyértelművé teszik, mit vizsgál a minta. A pozicionálási minták akkor a legerősebbek, ha a sorrend már hordozza a jelentést, például tuple-ökkel vagy más kis rendezett értékekkel.

Lásd még