Net State Machine
v0.4.0
Pustaka pembuat mesin negara untuk .NET.
Contoh berikut menunjukkan beberapa fungsi mesin negara.
menggunakan Enderlook.StateMachine; Karakter kelas publik{StateMachineFactory statis pribadi<States, Events, Character>? pabrik;private readonly Random rnd = new();private readonly StateMachine<States, Events, Character> stateMachine;private int health = 100;private int food = 100;private enum States{Sleep,Play,GettingFood, Hunt, Gather,} enum pribadi Events{HasFullHealth,LowHealth,IsHungry,IsNoLongerHungry,}public static async Task Main(){Character character = new(); while (true){Console.Clear();// Menjalankan panggilan pembaruan mesin negara dan meneruskan parameter sewenang-wenang padanya.// Parameter bersifat generik sehingga tidak mengalokasikan pada tipe nilai.// Parameter ini diteruskan ke delegasi berlangganan yang menerima tipe argumen generik di dalamnya tanda tangan.// Jika Anda tidak ingin meneruskan parameter, Anda dapat menghapus pemanggilan metode .With().// Sistem parameter ini juga dapat digunakan dengan metode peristiwa kebakaran.character.stateMachine.With(character.rnd.NextSingle ()).Update();Console.WriteLine($"Status: {character.stateMachine.CurrentState}.");Console.WriteLine($"Kesehatan: {character.health}.");Console.WriteLine($"Makanan: {character.food}.");await Task.Delay(10).ConfigureAwait(false);}}public Character(){// Membuat contoh dari status machine.stateMachine = GetStateMachineFactory().Create(this); // Alternatifnya jika Anda ingin meneruskan parameter ke inisialisasi mesin negara, Anda dapat melakukan: // stateMachine = GetStateMachineFactory().With(parameter).Create(this). // Metode `.With(parameter)` dapat digabungkan sebanyak yang Anda perlukan. // Pola `stateMachine.With(p1).With(p2)...With(pn).SomeMethod(...)` juga valid untuk metode `Fire()`, `FireImmediately()` dan `Update ()`.}statis pribadi StateMachineFactory<States, Events, Character> GetStateMachineFactory(){if (pabrik bukan null)kembalikan pabrik;StateMachineFactory<States, Acara, Karakter>? factory_ = StateMachine<States, Events, Character>// Mesin status dibuat dari pabrik sehingga membuat pembuatan banyak instance// lebih murah dalam CPU dan memori karena komputasi dilakukan satu kali dan dibagi di antara instance yang dibuat..CreateFactoryBuilder()// Menentukan keadaan awal mesin negara.// Parameter kedua menentukan bagaimana delegasi OnEntry harus dieksekusi selama inisialisasi mesin negara,// InitializationPolicy.Ignore berarti mereka tidak boleh run..SetInitialState(States.Sleep, InitializationPolicy.Ignore)// Mengonfigurasi sebuah state..In(States.Sleep)// Dieksekusi setiap kali kita masuk ke state ini..OnEntry(() => Console.WriteLine("Going ke tempat tidur."))// Dieksekusi setiap kali kita keluar dari keadaan ini..OnExit(() => Console.WriteLine("Getting up."))// Dieksekusi setiap kali metode pembaruan (Update() atau With<T>(T).Update()) dijalankan dan berada dalam status ini.// Semua peristiwa memberikan kelebihan beban untuk meneruskan ke penerima, sehingga dapat diparametisasi selama pembuatan contoh konkret.// Juga menyediakan kelebihan beban untuk meneruskan parameter tipe arbitrer, sehingga dapat diparametisasi selama panggilan With<T>(T).Update().// Juga menyediakan kelebihan beban untuk meneruskan baik penerima maupun parameter tipe arbitrer.// Kelebihan beban ini juga berlaku ke metode OnEntry(...), OnExit(...), If(...) dan Do(...)..OnUpdate(@this => @this.OnUpdateSleep()).On(Events.HasFullHealth )// Dieksekusi setiap kali peristiwa ini diaktifkan dalam keadaan ini..Do(() => Console.WriteLine("Pilih mainan."))// Keadaan baru untuk transit..Goto(States.Play)// Alternatifnya, Anda dapat mengonfigurasi eksekusi acara kebijakan selama transisi.// Pemanggilan metode di atas setara dengan:// .OnEntryPolicy(TransitionPolicy.ChildFirstWithCulling).OnExitPolicy(TransitionPolicy.ParentFirstWithCulling).Goto(States.Play)..On(Events.IsHungry)// Hanya dijalankan panggilan berikutnya jika kondisinya benar..If(@this => @this.IsVeryWounded())// Kita tetap dalam kondisi saat ini tanpa mengeksekusi delegasi OnEntry atau OnExit..StaySelf()// Metode di atas adalah jalan pintas dari:// .OnEntryPolicy(TransitionPolicy.Ignore).OnExitPolicy(TransitionPolicy.Ignore).Goto(States.Sleep).// Jika kita ingin jalankan delegasi yang dapat kita gunakan:// .GotoSelf(false)// Yang merupakan pintasan dari:// .OnEntryPolicy(TransitionPolicy.ChildFirstWithCullingInclusive).OnExitPolicy(TransitionPolicy.ParentFirstWithCullingInclusive).Goto(States.Sleep).// Jika selain itu, kami ingin mengeksekusi delegasi transisi dari negara induknya (sesuatu yang tidak berguna dalam contoh ini karena State.Sleep bukan substate) yang bisa kita lakukan:// .GotoSelf(true)// Yang merupakan pintasan dari:// .OnEntryPolicy(TransitionPolicy.ChildFirst).OnExitPolicy(TransitionPolicy.ParentFirst).Goto(States.Sleep).// Else jalankan panggilan berikutnya jika kondisinya benar..If(@this => @this.IsWounded()). Goto(States.Gather)// Else jalankan tanpa syarat..Goto(States.Hunt)// Abaikan peristiwa ini dalam transisi ini.// (Jika kami tidak menambahkan ini dan kami secara tidak sengaja mengaktifkan acara ini, pengecualian dilemparkan)..Ignore(Events.LowHealth)// Yang merupakan pintasan dari:// .On(Events.LowHealth).OnEntryPolicy(TransitionPolicy.Ignore). OnExitPolicy(TransitionPolicy.Ignore).Goto(States.Sleep)..In(States.Play).OnUpdate(@this => @this.OnUpdatePlay()).On(Events.IsHungry).If(@this => @this.IsWounded()).Goto(States.Gather).Goto(States.Hunt).In(States.GettingFood). OnEntry(() => Console.WriteLine("Mau makan.")).OnExit(() => Console.WriteLine("Berhenti pergi makan.")).In(States.Gather)// Menentukan bahwa ini negara bagian adalah subnegara bagian dari negara bagian lain.// Ini berarti bahwa delegasi OnUpdate di negara bagian induk juga akan dijalankan.// Juga bergantung pada OnEntryPolicy dan OnExitPolicy yang dikonfigurasi selama transisi,// delegasi OnEntry dan OnExit yang berlangganan di negara bagian ini dapat dijalankan selama transisi di subnegara bagian..IsSubStateOf(States.GettingFood).OnUpdate((Karakter @ini, parameter float) => @this.OnUpdateGather(parameter)).On(Events.IsNoLongerHungry).If(@this => @this.IsWounded()).Goto(States.Sleep).Goto(States.Play).On(Events.HasFullHealth) .Goto(States.Hunt).In(States.Hunt).IsSubStateOf(States.GettingFood).OnEntry(() => Console.WriteLine("Ambil busur.")).OnExit(() => Console.WriteLine("Jatuhkan busur.")).OnUpdate((Karakter @ini, parameter float) => @this.OnUpdateHunt(parameter)) .On(Events.IsNoLongerHungry).Goto(States.Sleep).On(Events.LowHealth).Goto(States.Sleep).Finalize();// The interlocked berguna untuk mengurangi penggunaan memori dalam situasi multithreading.// Hal ini karena pabrik berisi data umum antar instance,// jadi jika dua instance dibuat dari dua pabrik berbeda maka akan mengkonsumsi lebih banyak memori// dibandingkan dua instance yang dibuat dari pabrik yang sama pabrik.Interlocked.CompareExchange(ref pabrik, pabrik_, null);pabrik kembali;}bool pribadi IsVeryWounded() => kesehatan <= 50;bool pribadi IsWounded() => kesehatan <= 75;private void OnUpdateHunt(float lucky){food += (int)MathF.Round(rnd.Next(8) * lucky);if (makanan >= 100){food = 100;stateMachine.Fire(Events.IsNoLongerHungry) ; // Alternatifnya jika Anda ingin meneruskan parameter ke inisialisasi mesin negara, Anda dapat melakukan: // stateMachine.With(paramter).Fire(Events.IsNoLongerHungry);}kesehatan -= (int)MathF.Round(rnd.Next(6) * (1 - keberuntungan));if (kesehatan <= 20)stateMachine. Api(Events.LowHealth);}kekosongan pribadi OnUpdateGather(keberuntungan mengambang){makanan += (int)MathF.Round(rnd.Next(3) * keberuntungan);if (makanan >= 100){makanan = 100;stateMachine.Fire(Events.IsNoLongerHungry);}if (rnd.Next(1) % 1 == 0){health++;if (kesehatan >= 100){ kesehatan = 100;stateMachine.Fire(Events.HasFullHealth);}}}private void OnUpdatePlay(){makanan -= 3;if (makanan <= 0){makanan = 0;stateMachine.Fire(Events.IsHungry);}}private void OnUpdateSleep(){health++;if (kesehatan >= 100){health = 100;stateMachine.Fire(Events .HasFullHealth);}makanan -= 2;if (makanan <= 0){makanan = 0;stateMachine.Fire(Events.IsHungry);}}}
kelas tertutup publik StateMachine<TState, TEvent, TRecipient>di mana TState : notnullwhere TEvent : notnull{/// Dapatkan (sub)status terkini dari mesin status ini.public TState CurrentState { get; }/// Dapatkan (sub)status saat ini dan semua hierarki status induknya.public ReadOnlySlice<TState> CurrentStateHierarchy { get; }/// Dapatkan menerima acara berdasarkan (sub)state.public ReadOnlySlice<TEvent> CurrentAcceptedEvents { get; }/// Membuat pembuat pabrik. StateMachineBuilder statis publik<TState, TEvent, TRecipient> CreateFactoryBuilder();/// Dapatkan status induk dari status yang ditentukan./// Jika status bukan substat, kembalikan false.public bool GetParentStateOf(TState state, [NotNullWhen(true)] out TState? parentState);/// Dapatkan hierarki induk dari status yang ditentukan. Jika negara bukan subnegara, kembalikan kosong.public ReadOnlySlice<TState> GetParentHierarchyOf(TState state);/// Dapatkan kejadian yang diterima oleh negara yang ditentukan.public ReadOnlySlice<TEvent> GetAcceptedEventsBy(TState state);/// Menentukan jika keadaan saat ini adalah keadaan tertentu atau subkeadaan (bersarang) dari keadaan tertentu tersebut.public bool IsInState(TState state);/// Mengaktifkan event ke mesin status./// Jika mesin status sudah mengaktifkan status, mesin tersebut akan dijalankan setelah selesainya event saat ini. public void Fire(TEvent @event);/// Mengaktifkan event ke status mesin./// Acara tidak akan diantrekan tetapi benar-benar dijalankan, mengabaikan acara yang diantrekan sebelumnya./// Jika acara berikutnya diantrekan selama eksekusi callback acara ini, acara tersebut juga akan dijalankan setelah selesainya ini event.public void FireImmediately(TEvent @event);/// Menjalankan callback pembaruan yang terdaftar dalam keadaan saat ini.public void Update();/// Menyimpan parameter yang dapat diteruskan ke delegasi yang berlangganan.public ParametersBuilder With <T>(T parameter);public readonly struct ParametersBuilder{/// Menyimpan parameter yang dapat diteruskan ke callbacks.public ParametersBuilder Dengan<TParameter>(TParameter parameter);/// Sama seperti Fire(TEvent) di kelas induk tetapi menyertakan semua nilai tersimpan yang dapat diteruskan ke delegasi yang berlangganan.public void Fire(TEvent);/// Sama seperti FireImmediately(TEvent) di kelas induk tetapi menyertakan semua nilai tersimpan yang dapat diteruskan ke delegasi yang berlangganan.public void FireImmediately(TEvent);/// Sama seperti Update(TEvent) di kelas induk tetapi mencakup semua nilai tersimpan yang dapat diteruskan ke delegasi yang berlangganan.public void Update(TEvent);}public readonly struct InitializeParametersBuilder{/// Menyimpan parameter yang dapat diteruskan ke callbacks.public InitializeParametersBuilder With<TParameter>(parameter TParameter);/// Membuat mesin status.public StateMachine<TState, TEvent, TRecipient> Buat(TRecipient penerima);}}kelas StateMachineFactory yang disegel publik<TState, TEvent, TRecipient>di mana TState : notnullwhere TEvent : notnull{/// Membuat mesin status yang dikonfigurasi dan diinisialisasi menggunakan konfigurasi yang disediakan oleh pabrik ini.public StateMachine<TState, TEvent, TRecipient> Create(TRecipient receiver);/// Menyimpan parameter yang dapat diteruskan ke delegasi yang berlangganan.public StateMachine<TState, TEvent, TRecipient>.InitializeParametersBuilder With<T>(T parameter);}kelas tertutup publik StateMachineBuilder<TState, TEvent, TRecipient> : IFinalizablewhere TState : notnullwhere TEvent : notnull{/// Menentukan status awal mesin status./// `initializationPolicy` menentukan cara delegasi berlangganan ke oven OnEntry dari status yang ditentukan (dan induk negara bagian) akan dijalankan selama inisialisasi mesin negara.public StateMachineBuilder<TState, TEvent, TRecipient> SetInitialState(TState state, ExecutionPolicy initializationPolicy = ExecutionPolicy.ChildFirst);/// Tambahkan status baru atau muat status yang ditambahkan sebelumnya.public StateBuilder<TState, TEvent, TRecipient> In(TState state);/// Membuat pabrik dari menggunakan sebagai konfigurasi pembangun.public StateMachineFactory<TState, TEvent, TRecipient> Finalize();}public kelas tersegel StateBuilder<TState, TEvent, TRecipient> : IFinalizablewhere TState : notnullwhere TEvent : notnull{/// Meneruskan panggilan ke StateMachineBuilder<TState, TEvent, TRecipient>.In(TState state).public StateBuilder<TState, TEvent, TRecipient> In (negara bagian TS);/// Meneruskan panggilan ke StateMachineBuilder<TState, TEvent, TRecipient>.Finalize();public StateMachineFactory<TState, TEvent, TRecipient> Finalize();/// Menandai status ini sebagai substatus dari status yang ditentukan.public StateBuilder<TState, TEvent, TRecipient> IsSubStateOf (TSstate state);/// Menentukan tindakan yang akan dijalankan saat masuk ke state.public ini StateBuilder<TState, TEvent, TRecipient> OnEntry(Action action);/// Sama seperti OnEntry(Action) tetapi meneruskan penerima sebagai parameter.public StateBuilder<TState, TEvent, TRecipient> OnEntry(Action<TRecipient> action);// / Sama seperti OnEntry(Action) tetapi meneruskan ke delegasi parameter apa pun yang diteruskan selama panggilan yang cocok dengan tipe parameter generik./// Jika tidak ada parameter yang diteruskan dengan parameter generik yang ditentukan ditemukan, diabaikan. public StateBuilder<TState, TEvent, TRecipient> OnEntry<TParameter>(Action<TParameter> action);/// Versi gabungan dari OnEntry(Action<TRecipient>) dan OnEntry(Action<TParameter>).public StateBuilder<TState, TEvent, TRecipient> OnEntry<TParameter>(Action<TRecipient, TParameter> action);/// Menentukan tindakan yang akan dijalankan saat keluar dari state ini.public StateBuilder<TState, TEvent, TRecipient> OnExit(Action action);/// Sama seperti OnExit(Action) tetapi meneruskan penerima sebagai parameter.public StateBuilder <TState, TEvent, TRecipient> OnExit(Action<TRecipient> action);/// Sama seperti OnExit(Action) tetapi meneruskan ke delegasi parameter apa pun yang diteruskan selama panggilan yang cocok dengan tipe parameter generik./// Jika tidak ditemukan parameter yang diteruskan dengan parameter generik yang ditentukan, maka akan diabaikan.public StateBuilder<TState, TEvent, TRecipient> OnExit<TParameter>(Action<TParameter> action);/// Versi gabungan OnExit(Action<TRecipient>) dan OnExit(Action<TParameter>).public StateBuilder<TState, TEvent, TRecipient> OnExit<TParameter>(Action<TRecipient, TParameter> action);/// Menentukan tindakan yang akan dijalankan pada pembaruan status ini.public StateBuilder<TState, TEvent, TRecipient> OnUpdate(Action action);/// Sama seperti OnUpdate( Action) tetapi meneruskan penerima sebagai parameter.public StateBuilder<TState, TEvent, TRecipient> OnUpdate(Action<TRecipient> action);/// Sama seperti OnUpdate(Action) tetapi meneruskan ke delegasi parameter apa pun yang diteruskan selama panggilan yang cocok dengan tipe parameter generik. public StateBuilder<TState, TEvent, TRecipient> OnUpdate<TParameter>(Action<TParameter> action);/// Versi gabungan dari OnUpdate(Action<TRecipient>) dan OnUpdate(Action<TParameter>)./// Jika tidak ditemukan parameter yang diteruskan dengan parameter generik yang ditentukan, maka parameter tersebut akan diabaikan.publik StateBuilder<TState, TEvent, TRecipient> OnUpdate<TParameter>(Action<TRecipient, TParameter> action);/// Tambahkan perilaku yang dieksekusi selama pengaktifan event yang ditentukan.public TransitionBuilder<TState, TEvent, TRecipient, StateBuilder< TState, TEvent, TRecipient>> On(TEvent @event);/// Mengabaikan kejadian yang ditentukan./// Jika tidak ada perilaku ditambahkan ke suatu acara dan dipecat, maka akan dilempar. Ini mencegah pelemparan dengan mengabaikan panggilan sama sekali.public StateBuilder<TState, TEvent, TRecipient> Ignore(TEvent @event);}public disegel class TransitionBuilder<TState, TEvent, TRecipient, TParent> : IFinalizable, ITransitionBuilder<TState>where TState : notnullwhere TEvent : notnull{/// Tambahkan sub transisi yang dijalankan ketika delegasi mengembalikan true.public TransitionBuilder<TState, TEvent, TRecipient, TransitionBuilder<TState, TEvent, TRecipient, TParent>> If(Func<bool> guard);/// Sama seperti If(Func<bool>) tetapi meneruskan penerima sebagai parameter.public TransitionBuilder< TState, TEvent, TRecipient, TransitionBuilder<TState, TEvent, TRecipient, TParent>> If(Func<TRecipient, bool> guard);/// Sama seperti If(Func<bool>) tetapi meneruskan ke delegasi parameter apa pun yang diteruskan selama panggilan yang cocok dengan tipe parameter generik.public TransitionBuilder<TState, TEvent, TRecipient, TransitionBuilder<TState, TEvent, TRecipient, TParent>> If<TParameter>(Func<TParameter, bool> guard);/// Versi gabungan dari If(Func<TRecipient, bool>) dan If(Func<TParameter, bool>).public TransitionBuilder<TState, TEvent, TRecipient, TransitionBuilder<TState, TEvent, TRecipient, TParent>> If<TParameter>(Func<TParameter, bool > penjaga);/// Menentukan tindakan yang akan dijalankan ketika peristiwa dimunculkan.public TransitionBuilder<TState, TEvent, TRecipient, TParent> Do(Action action);/// Sama seperti Do(Action) tetapi meneruskan penerima sebagai parameter.public TransitionBuilder<TState, TEvent, TRecipient, TParent> Do(Action<TRecipient> action);/// Sama sebagai Do(Action) tetapi teruskan ke delegasi parameter apa pun yang diteruskan selama panggilan yang cocok dengan tipe parameter generik./// Jika tidak ada parameter yang diteruskan dengan parameter generik tertentu yang ditemukan, parameter tersebut akan diabaikan.publik TransitionBuilder<TState, TEvent, TRecipient, TParent> Do<TParameter>(Action<TParameter> action);/// Versi gabungan dari Do(Action<TRecipient>) dan Do(Action<TParameter>).public TransitionBuilder<TState, TEvent , TRecipient, TParent> Do<TParameter>(Action<TRecipient, TParameter> action);/// Mengonfigurasi kebijakan tentang bagaimana delegasi yang berlangganan pada hook entri harus dieksekusi./// Jika metode ini tidak dijalankan, kebijakan defaultnya adalah TransitionPolicy.ParentFirstWithCulling.public GotoBuilder<TState, TEvent, TRecipient, TParent> OnEntryPolicy(TransitionPolicy policy);// / Mengonfigurasi kebijakan bagaimana delegasi yang berlangganan pada hook keluar harus dieksekusi./// Jika metode ini tidak dijalankan, kebijakan defaultnya adalah TransitionPolicy.ChildFirstWithCulling.public GotoBuilder<TState, TEvent, TRecipient, TParent> OnExitPolicy(TransitionPolicy policy);/// Menentukan status transisi ini./// Ini setara dengan: OnEntryPolicy(TransitionPolicy.ChildFirstWithCulling).OnExitPolicy(TransitionPolicy.ParentFirstWithCulling).Goto(state).public TParent Goto(TState state);/// Menentukan untuk transit ke keadaan saat ini./// Jika runParentsActions benar: tindakan OnExit dan OnEntry keadaan saat ini (tetapi bukan negara bagian induk jika keadaan saat ini merupakan subnegara bagian) adalah dieksekusi./// Ini setara dengan OnEntryPolicy(TransitionPolicy.ChildFirstWithCullingInclusive).OnExitPolicy(TransitionPolicy.ParentFirstWithCullingInclusive).Goto(currentState)./// Jika runParentActions salah: tindakan OnExit dan OEntry pada kondisi saat ini (dan induknya jika terjadi keadaan saat ini menjadi subnegara bagian) akan dieksekusi./// Ini setara dengan OnEntryPolicy(TransitionPolicy.ChildFirst).OnExitPolicy(TransitionPolicy.ParentFirst).Goto(currentState).public TParent GotoSelf(bool runParentsActions = false);/// Menentukan bahwa tidak akan ada transisi ke keadaan mana pun, jadi tidak akan ada kejadian OnEntry atau OnExit dibangkitkan./// Ini setara dengan OnEntryPolicy(TransitionPolicy.Ignore).OnExitPolicy(TransitionPolicy.Ignore).GotoSelf().public TParent StaySelf();}kelas tersegel publik GotoBuilder<TState, TEvent, TRecipient, TParent> : IGoto<TState>where TState : notnullwhere TEvent : notnull {/// Mengonfigurasi kebijakan tentang bagaimana seharusnya delegasi yang berlangganan pada entry hook dijalankan./// Jika metode ini tidak dijalankan, kebijakan defaultnya adalah TransitionPolicy.ParentFirstWithCulling.public GotoBuilder<TState, TEvent, TRecipient, TParent> OnEntryPolicy(TransitionPolicy policy);/// Mengonfigurasi kebijakan bagaimana delegasi berlangganan pada on exit hook harus dijalankan./// Jika metode ini tidak dijalankan, kebijakan defaultnya adalah TransitionPolicy.ChildrenFirstWithCulling.public GotoBuilder<TState, TEvent, TRecipient, TParent> OnExitPolicy(TransitionPolicy policy);/// Menentukan ke negara bagian mana transisi ini berlangsung.public TParent Goto(TState state);/// Menentukan untuk transit ke keadaan saat ini ./// Ini adalah pintasan dari Goto(currentState).public TParent GotoSelf();}/// Menentukan kebijakan transisi antara dua negara bagian./// Ini mengonfigurasi cara delegasi yang berlangganan di negara bagian dijalankan selama transisi antar negara bagian.public enum TransitionPolicy{/// Menentukan bahwa delegasi yang berlangganan tidak boleh berjalan.Ignore = 0,/// Menentukan bahwa berlangganan delegasi pada orang tua dijalankan terlebih dahulu.ParentFirst = 1,/// Menentukan bahwa delegasi berlangganan pada anak dijalankan terlebih dahulu.ChildFirst = 2,/// Menentukan bahwa delegasi berlangganan pada orang tua dijalankan pertama dari (tidak termasuk) induk bersama terakhir di antara kedua negara bagian.ParentFirstWithCulling = 3,/// Menentukan bahwa delegasi berlangganan pada turunan dijalankan terlebih dahulu hingga mencapai (tidak termasuk) orang tua bersama terakhir di antara kedua negara bagian.ChildFirstWithCulling = 4,// / Menentukan bahwa delegasi yang berlangganan pada orang tua dijalankan pertama kali dari (termasuk) orang tua terakhir yang sama antara kedua negara bagian.ParentFirstWithCullingInclusive = 5,/// Menentukan bahwa delegasi yang berlangganan pada anak dijalankan terlebih dahulu hingga mencapai (termasuk) induk umum terakhir di antara kedua negara bagian.ChildFirstWithCullingInclusive = 6,}/// Mewakili sepotong data.public readonly struct ReadOnlySlice<T> : IReadOnlyList<T>{// Dapatkan elemennya ditentukan di indeks.publik T ini[int indeks] { dapatkan; }/// Dapatkan jumlah irisan.public int Count { get; }/// Dapatkan <see cref="ReadOnlyMemory{T}"/> dari irisan ini.public ReadOnlyMemory<T> Memory { get; }/// Dapatkan <see cref="ReadOnlySpan{T}"/> dari irisan ini.public ReadOnlySpan<T> Span { get; }/// Dapatkan enumerator dari irisan.public Enumerator GetEnumerator();/// Enumerator dari <see cref="ReadOnlySlice{T}"/>.public struct Enumerator : IEnumerator<T>{/// Dapatkan elemen saat ini dari enumerator.public T Saat Ini { dapatkan; }/// Pindah ke elemen berikutnya dari enumeration.public bool MoveNext();/// Reset enumeration.public void Reset();}}