コード例 #1
0
ファイル: UnsubscriberBag.cs プロジェクト: ikorin24/Elffy
            static void OnDispose(object r, Delegate f)
            {
                var raiser = SafeCast.As <EventRaiser <T> >(r);
                var func   = SafeCast.As <Action <T> >(f);

                raiser.Unsubscribe(func);
            }
コード例 #2
0
 private static void StartOrReservePrivate <TParent, TState>(TParent parent, TState state, Delegate coroutine, Action <Exception>?onCatch, FrameTiming timing) where TParent : class
 {
     if (typeof(TParent) == typeof(IHostScreen))
     {
         var parentScreen = SafeCast.As <IHostScreen>(parent);
         if (parentScreen.IsRunning == false)
         {
             ReserveCoroutine(parentScreen, state, coroutine, onCatch, timing);
         }
         else
         {
             StartCoroutine(new CoroutineState(parentScreen), state, coroutine, onCatch, timing).Forget();
         }
     }
     else if (typeof(TParent) == typeof(FrameObject))
     {
         var parentFrameObject = SafeCast.As <FrameObject>(parent);
         if (parentFrameObject.LifeState.IsBefore(LifeState.Alive))
         {
             ReserveCoroutine(parentFrameObject, state, coroutine, null, timing);
         }
         else
         {
             StartCoroutine(new CoroutineState(parentFrameObject), state, coroutine, null, timing).Forget();
         }
     }
     else
     {
         Debug.Fail("Something wrong");
     }
 }
コード例 #3
0
 public static bool TryGetArray4Fast([MaybeNullWhen(false)] out object?[] instance)
 {
     // If the exclusion control is successfully obtained, I try to get the instance from the pool.
     if (_lock.TryEnter() == false)
     {
         instance = null;
         return(false);
     }
     try {
         instance = _root;
         if (instance is not null)
         {
             Debug.Assert(_pooledCount > 0);
             Debug.Assert(instance.Length == LengthOfPoolTargetArray);
             _pooledCount--;
             _root = SafeCast.As <object?[]>(MemoryMarshal.GetArrayDataReference(instance)); // _root = (object?[])instance[0];
             MemoryMarshal.GetArrayDataReference(instance) = null;                           // instance[0] = null;
             return(true);
         }
         return(false);
     }
     finally {
         _lock.Exit();
     }
 }
コード例 #4
0
 private static UniTask StartPrivate <TParent, TState>(TParent parent, TState state, Delegate coroutine, FrameTiming timing) where TParent : class
 {
     if (typeof(TParent) == typeof(IHostScreen))
     {
         var parentScreen = SafeCast.As <IHostScreen>(parent);
         if (parentScreen.IsRunning == false)
         {
             ThrowParentNotAlive();
             return(UniTask.CompletedTask);
         }
         else
         {
             return(StartCoroutine(new CoroutineState(parentScreen), state, coroutine, null, timing));
         }
     }
     else if (typeof(TParent) == typeof(FrameObject))
     {
         var parentFrameObject = SafeCast.As <FrameObject>(parent);
         if (parentFrameObject.LifeState.IsBefore(LifeState.Alive))
         {
             ThrowParentNotAlive();
             return(UniTask.CompletedTask);
         }
         else
         {
             return(StartCoroutine(new CoroutineState(parentFrameObject), state, coroutine, null, timing));
         }
     }
     else
     {
         Debug.Fail("Something wrong");
         return(UniTask.CompletedTask);
     }
 }
コード例 #5
0
ファイル: UIRenderable.cs プロジェクト: ikorin24/Elffy
 public UIRenderable(Control control)
 {
     Debug.Assert(control is not null);
     _control  = control;
     IsFrozen  = true;       // disable calling update method per frame
     HasShadow = false;
     Activating.Subscribe((f, ct) => SafeCast.As <UIRenderable>(f).OnActivating());
 }
コード例 #6
0
        public void CastValidArgumentTest()
        {
            object input = "123";

            var result = SafeCast.CastArgument <string>(input, "arg");

            Assert.AreEqual(input, result);
        }
コード例 #7
0
        public void CastValidValueTest()
        {
            object input = "123";

            var result = SafeCast.Cast <string>(input, "text {0}", "text");

            Assert.AreEqual(input, result);
        }
コード例 #8
0
ファイル: Grid.cs プロジェクト: ikorin24/Elffy
            protected override ContentAreaInfo MesureContentArea(Control parent, Control target)
            {
                var grid = SafeCast.As <Grid>(parent);

                var padding          = grid.Padding;
                var gridContentsSize = grid.ActualSize - new Vector2(padding.Left + padding.Right, padding.Top + padding.Bottom);
                var col = grid.GetColumnOf(target);
                var row = grid.GetRowOf(target);

                var(cellSize, cellPos) = grid.GetCellSizePos(gridContentsSize, col, row);
                return(new ContentAreaInfo(cellPos, cellSize, LayoutThickness.Zero));
            }
コード例 #9
0
 internal void Unsubscribe(Func <T, CancellationToken, UniTask>?func)
 {
     if (func is null)
     {
         return;
     }
     _lock.Enter();          // ---- enter
     try {
         var funcs = _funcs;
         var count = _count;
         if (count == 0)
         {
             Debug.Assert(_funcs == null);
             return;
         }
         else if (count == 1)
         {
             if (ReferenceEquals(_funcs, func))
             {
                 _count = 0;
                 _funcs = null;
             }
             return;
         }
         else
         {
             var funcSpan = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask>[]>(funcs).AsSpan(0, count);
             for (int i = 0; i < funcSpan.Length; i++)
             {
                 if (funcSpan[i] == func)
                 {
                     _count = count - 1;
                     if (i < _count)
                     {
                         var copyLen = _count - i;
                         funcSpan.Slice(i + 1, copyLen).CopyTo(funcSpan.Slice(i));
                     }
                     funcSpan[_count] = null !;
                     if (_count == 1)
                     {
                         _funcs = funcSpan[0];
                     }
                     return;
                 }
             }
             return;
         }
     }
     finally {
         _lock.Exit();       // ---- exit
     }
 }
コード例 #10
0
ファイル: EventRaiser.cs プロジェクト: ikorin24/Elffy
        internal void Subscribe(Action <T> action)
        {
            Debug.Assert(action is not null);
            _lock.Enter();          // ---- enter
            try {
                var count = _count;
                if (count == 0)
                {
                    Debug.Assert(_actions is null);
                    _actions = action;
                }
                else if (count == 1)
                {
                    Debug.Assert(_actions is Action <T>);

                    if (ArrayPoolForEventRaiser.TryGetArray4Fast(out var actions) == false)
                    {
                        actions = new object[DefaultBufferCapacity];
                    }
                    Debug.Assert(actions.Length >= 2);
                    MemoryMarshal.GetArrayDataReference(actions) = _actions;
                    Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(actions), 1) = action;
                    _actions = actions;
                }
                else
                {
                    var actions = SafeCast.NotNullAs <object?[]>(_actions);
                    if (actions.Length == count)
                    {
                        var newActions = new object[actions.Length * 2];
                        actions.AsSpan().CopyTo(newActions);
                        if (actions.Length == ArrayPoolForEventRaiser.LengthOfPoolTargetArray)
                        {
                            actions[0] = null;
                            actions[1] = null;
                            actions[2] = null;
                            actions[3] = null;
                            ArrayPoolForEventRaiser.ReturnArray4Fast(actions);
                        }
                        _actions = newActions;
                        actions  = newActions;
                    }
                    actions[count] = action;
                }
                _count = count + 1;
            }
            finally {
                _lock.Exit();       // ---- exit
            }
        }
コード例 #11
0
        private static async UniTask StartCoroutine <TState>(CoroutineState coroutineState, TState state, Delegate coroutine, Action <Exception>?onCatch, FrameTiming timing)
        {
            var fo = coroutineState.FrameObject;

            if (fo is null)
            {
                if (coroutineState.Screen.IsRunning == false)
                {
                    return;
                }
            }
            else
            {
                Debug.Assert(fo.LifeState.IsSameOrAfter(LifeState.Alive));
                if (fo.LifeState == LifeState.Dead)
                {
                    return;
                }
            }
            try {
                await coroutineState.TimingOf(timing).Next();

                if (typeof(TState) == typeof(DummyState))
                {
                    var noStateCoroutine = SafeCast.As <Func <CoroutineState, UniTask> >(coroutine);
                    await noStateCoroutine(coroutineState);
                }
                else
                {
                    var statefulCoroutine = SafeCast.As <Func <CoroutineState, TState, UniTask> >(coroutine);
                    await statefulCoroutine(coroutineState, state);
                }
            }
            catch (Exception ex) {
                if (onCatch != null)
                {
                    onCatch.Invoke(ex);
                }
                else
                {
                    if (EngineSetting.UserCodeExceptionCatchMode == UserCodeExceptionCatchMode.Throw)
                    {
                        throw;
                    }
                }
            }
        }
コード例 #12
0
        private UniTask RaiseCore(T arg, CancellationToken cancellationToken, EventRaiseMode mode)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(UniTask.FromCanceled(cancellationToken));
            }

            // When _count == 0, there is no need to perform exclusive locking.
            if (_count == 0)
            {
                return(UniTask.CompletedTask);
            }

            _lock.Enter();          // ---- enter
            // Get _count after exclusive locking.
            var count = _count;

            if (count == 1)
            {
                var func = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask> >(_funcs);
                _lock.Exit();       // ---- exit
                return(func.Invoke(arg, cancellationToken));
            }
            else
            {
                var funcArray = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask>[]>(_funcs);
                var funcs     = funcArray.AsSpan(0, count);
                PooledAsyncEventFuncs <Func <T, CancellationToken, UniTask> > copiedFuncs;
                try {
                    copiedFuncs = new PooledAsyncEventFuncs <Func <T, CancellationToken, UniTask> >(count);
                    funcs.CopyTo(copiedFuncs.AsSpan());
                }
                finally {
                    _lock.Exit();       // ---- exit
                }
                if (mode == EventRaiseMode.Parallel)
                {
                    return(OrderedParallelAsyncEventPromise <T> .CreateTask(copiedFuncs, arg, cancellationToken));
                }
                else
                {
                    Debug.Assert(mode == EventRaiseMode.Sequential);
                    return(OrderedSequentialAsyncEventPromise <T> .CreateTask(copiedFuncs, arg, cancellationToken));
                }
            }
        }
コード例 #13
0
 public static bool TryGetArray4([MaybeNullWhen(false)] out object?[] instance)
 {
     _lock.Enter();
     try {
         instance = _root;
         if (instance is not null)
         {
             Debug.Assert(_pooledCount > 0);
             Debug.Assert(instance.Length == LengthOfPoolTargetArray);
             _pooledCount--;
             _root = SafeCast.As <object?[]>(MemoryMarshal.GetArrayDataReference(instance)); // _root = (object?[])instance[0];
             MemoryMarshal.GetArrayDataReference(instance) = null;                           // instance[0] = null;
             return(true);
         }
         return(false);
     }
     finally {
         _lock.Exit();
     }
 }
コード例 #14
0
ファイル: EventRaiser.cs プロジェクト: ikorin24/Elffy
        public void Raise(T arg)
        {
            // When _count == 0, there is no need to perform exclusive locking.
            if (_count == 0)
            {
                return;
            }

            _lock.Enter();          // ---- enter
            // Get _count after exclusive locking.
            var count = _count;

            if (count == 1)
            {
                var action = SafeCast.NotNullAs <Action <T> >(_actions);
                _lock.Exit();       // ---- exit
                action.Invoke(arg);
                return;
            }
            else
            {
                using var mem = new RefTypeRentMemory <object?>(count);
                Span <object?> memSpan;
                try {
                    var actions = SafeCast.NotNullAs <object?[]>(_actions).AsSpan(0, count);
                    memSpan = mem.AsSpan();
                    actions.CopyTo(memSpan);
                }
                finally {
                    _lock.Exit();   // ---- exit
                }
                foreach (var action in memSpan)
                {
                    SafeCast.NotNullAs <Action <T> >(action).Invoke(arg);
                }
                return;
            }
        }
コード例 #15
0
 internal void Subscribe(Func <T, CancellationToken, UniTask> func)
 {
     Debug.Assert(func is not null);
     _lock.Enter();          // ---- enter
     try {
         var count = _count;
         if (count == 0)
         {
             Debug.Assert(_funcs is null);
             _funcs = func;
         }
         else if (count == 1)
         {
             var funcs = new Func <T, CancellationToken, UniTask> [DefaultBufferCapacity];
             funcs[0] = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask> >(_funcs);
             funcs[1] = func;
             _funcs   = funcs;
         }
         else
         {
             var funcs = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask>[]>(_funcs);
             if (funcs.Length == count)
             {
                 var newFuncs = new Func <T, CancellationToken, UniTask> [funcs.Length * 2];
                 funcs.AsSpan().CopyTo(newFuncs);
                 _funcs = newFuncs;
                 funcs  = newFuncs;
             }
             funcs[count] = func;
         }
         _count = count + 1;
     }
     finally {
         _lock.Exit();       // ---- exit
     }
     return;
 }
コード例 #16
0
        public void CastInvalidArgumentTest()
        {
            var action = new TestDelegate(() => SafeCast.CastArgument <string>(new object(), "arg"));

            Assert.That(action, Throws.ArgumentException);
        }
コード例 #17
0
ファイル: EventRaiser.cs プロジェクト: ikorin24/Elffy
 internal void Unsubscribe(Action <T>?action)
 {
     if (action is null)
     {
         return;
     }
     _lock.Enter();          // ---- enter
     try {
         var actions = _actions;
         var count   = _count;
         if (count == 0)
         {
             Debug.Assert(actions is null);
             return;
         }
         else if (count == 1)
         {
             if (ReferenceEquals(_actions, action))
             {
                 _count   = 0;
                 _actions = null;
             }
             return;
         }
         else
         {
             var actionSpan = SafeCast.NotNullAs <object?[]>(actions).AsSpan(0, count);
             for (int i = 0; i < actionSpan.Length; i++)
             {
                 if (ReferenceEquals(actionSpan[i], action))
                 {
                     _count = count - 1;
                     if (i < _count)
                     {
                         var copyLen = _count - i;
                         actionSpan.Slice(i + 1, copyLen).CopyTo(actionSpan.Slice(i));
                     }
                     actionSpan[_count] = null;
                     if (_count == 1)
                     {
                         var a            = actionSpan[0];
                         var actionsArray = SafeCast.NotNullAs <object?[]>(actions);
                         if (actionsArray.Length == ArrayPoolForEventRaiser.LengthOfPoolTargetArray)
                         {
                             actionsArray[0] = null;
                             actionsArray[1] = null;
                             actionsArray[2] = null;
                             actionsArray[3] = null;
                             ArrayPoolForEventRaiser.ReturnArray4Fast(actionsArray);
                         }
                         _actions = a;
                     }
                     return;
                 }
             }
             return;
         }
     }
     finally {
         _lock.Exit();       // ---- exit
     }
 }
コード例 #18
0
 public SkySphere()
 {
     Activating.Subscribe((f, ct) => SafeCast.As <SkySphere>(f).OnActivating());
 }
コード例 #19
0
        public void CastInvalidValueTest()
        {
            var action = new TestDelegate(() => SafeCast.Cast <string>(new object(), "text {0}", "text"));

            Assert.That(action, Throws.InvalidOperationException);
        }
コード例 #20
0
 public DeferredRenderingLayer(int sortNumber = DRLayerDefaultSort) : base(sortNumber)
 {
     _gBuffer     = new GBuffer();
     _postProcess = new PbrDeferredRenderingPostProcess(this, static screen => ref screen.Camera.View);
     Activating.Subscribe((l, ct) => SafeCast.As <DeferredRenderingLayer>(l).OnActivating());
 }
コード例 #21
0
ファイル: UIRenderable.cs プロジェクト: ikorin24/Elffy
 public bool TryGetUILayer([MaybeNullWhen(false)] out UILayer layer)
 {
     layer = SafeCast.As <UILayer>(Layer);
     return(layer is not null);
 }
コード例 #22
0
        public void CastNullArgumentTest()
        {
            var action = new TestDelegate(() => SafeCast.CastArgument <string>(null, "arg"));

            Assert.That(action, Throws.InstanceOf <ArgumentNullException>());
        }
コード例 #23
0
ファイル: SkyBox.cs プロジェクト: ikorin24/Elffy
 public SkyBox()
 {
     Activating.Subscribe((f, ct) => SafeCast.As <SkyBox>(f).OnActivating());
 }
コード例 #24
0
 static CanCastStep()
 {
     stackVariable0 = new Binary();
     stackVariable1 = new SafeCast();
     stackVariable1.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_0));
     stackVariable0.set_Left(stackVariable1);
     stackVariable5 = new Constant();
     stackVariable5.set_Value((BinaryOperator)10);
     stackVariable0.set_Operator(stackVariable5);
     stackVariable8 = new Literal();
     stackVariable8.set_Value(null);
     stackVariable0.set_Right(stackVariable8);
     CanCastStep.canCastToReferenceTypePattern = stackVariable0;
     stackVariable10 = new Binary();
     stackVariable11 = new SafeCast();
     stackVariable11.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_1));
     stackVariable10.set_Left(stackVariable11);
     stackVariable15 = new Constant();
     stackVariable15.set_Value((BinaryOperator)9);
     stackVariable10.set_Operator(stackVariable15);
     stackVariable18 = new Literal();
     stackVariable18.set_Value(null);
     stackVariable10.set_Right(stackVariable18);
     CanCastStep.negatedCanCastToReferenceTypePattern = stackVariable10;
     stackVariable20 = new Binary();
     stackVariable21 = new SafeCast();
     stackVariable21.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_2));
     stackVariable20.set_Left(stackVariable21);
     stackVariable25 = new Constant();
     stackVariable25.set_Value((BinaryOperator)10);
     stackVariable20.set_Operator(stackVariable25);
     stackVariable28 = new Literal();
     stackVariable28.set_Value(0);
     stackVariable20.set_Right(stackVariable28);
     CanCastStep.canCastToValueTypePattern = stackVariable20;
     stackVariable31 = new Binary();
     stackVariable32 = new SafeCast();
     stackVariable32.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_3));
     stackVariable31.set_Left(stackVariable32);
     stackVariable36 = new Constant();
     stackVariable36.set_Value((BinaryOperator)9);
     stackVariable31.set_Operator(stackVariable36);
     stackVariable39 = new Literal();
     stackVariable39.set_Value(0);
     stackVariable31.set_Right(stackVariable39);
     CanCastStep.negatedCanCastToValueTypePattern = stackVariable31;
     stackVariable42 = new Binary();
     stackVariable43 = new SafeCast();
     stackVariable43.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_4));
     stackVariable42.set_Left(stackVariable43);
     stackVariable47 = new Constant();
     stackVariable47.set_Value((BinaryOperator)15);
     stackVariable42.set_Operator(stackVariable47);
     stackVariable50 = new Literal();
     stackVariable50.set_Value(null);
     stackVariable42.set_Right(stackVariable50);
     CanCastStep.canCastComparisonToNullPattern = stackVariable42;
     stackVariable52 = new Binary();
     stackVariable53 = new SafeCast();
     stackVariable53.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_5));
     stackVariable52.set_Left(stackVariable53);
     stackVariable57 = new Constant();
     stackVariable57.set_Value((BinaryOperator)14);
     stackVariable52.set_Operator(stackVariable57);
     stackVariable60 = new Literal();
     stackVariable60.set_Value(null);
     stackVariable52.set_Right(stackVariable60);
     CanCastStep.negatedCanCastComparisonToNullPattern = stackVariable52;
     stackVariable62 = new Binary();
     stackVariable63 = new SafeCast();
     stackVariable63.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_6));
     stackVariable62.set_Left(stackVariable63);
     stackVariable67 = new Constant();
     stackVariable67.set_Value((BinaryOperator)15);
     stackVariable62.set_Operator(stackVariable67);
     stackVariable70 = new Literal();
     stackVariable70.set_Value(0);
     stackVariable62.set_Right(stackVariable70);
     CanCastStep.canCastComparisonToZeroPattern = stackVariable62;
     stackVariable73 = new Binary();
     stackVariable74 = new SafeCast();
     stackVariable74.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_7));
     stackVariable73.set_Left(stackVariable74);
     stackVariable78 = new Constant();
     stackVariable78.set_Value((BinaryOperator)14);
     stackVariable73.set_Operator(stackVariable78);
     stackVariable81 = new Literal();
     stackVariable81.set_Value(0);
     stackVariable73.set_Right(stackVariable81);
     CanCastStep.negatedCanCastComparisonToZeroPattern = stackVariable73;
     stackVariable84 = new Binary();
     stackVariable85 = new SafeCast();
     stackVariable85.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_8));
     stackVariable84.set_Left(stackVariable85);
     stackVariable89 = new Constant();
     stackVariable89.set_Value((BinaryOperator)10);
     stackVariable84.set_Operator(stackVariable89);
     stackVariable92 = new Literal();
     stackVariable92.set_Value(false);
     stackVariable84.set_Right(stackVariable92);
     CanCastStep.canCastComparisonToFalsePattern = stackVariable84;
     stackVariable95 = new Binary();
     stackVariable96 = new SafeCast();
     stackVariable96.set_Bind(new Func <SafeCastExpression, MatchData>(CanCastStep.u003cu003ec.u003cu003e9.u003cu002ecctoru003eb__16_9));
     stackVariable95.set_Left(stackVariable96);
     stackVariable100 = new Constant();
     stackVariable100.set_Value((BinaryOperator)9);
     stackVariable95.set_Operator(stackVariable100);
     stackVariable103 = new Literal();
     stackVariable103.set_Value(false);
     stackVariable95.set_Right(stackVariable103);
     CanCastStep.negatedCanCastComparisonToFalsePattern = stackVariable95;
     return;
 }
コード例 #25
0
 public Cube()
 {
     Activating.Subscribe((f, ct) => SafeCast.As <Cube>(f).OnActivating());
 }
コード例 #26
0
 private static void ReserveCoroutine <TParent, TState>(TParent parent, TState state, Delegate coroutine, Action <Exception>?onCatch, FrameTiming timing)
     where TParent : class
 {
     if (typeof(TParent) == typeof(IHostScreen))
     {
         var parentScreen = SafeCast.As <IHostScreen>(parent);
         if (typeof(TState) == typeof(DummyState))
         {
             if (onCatch is null)
             {
                 // [capture] coroutine, timing
                 parentScreen.Initialized += p => StartCoroutine(new CoroutineState(p), DummyState.Null, coroutine, null, timing).Forget();
             }
             else
             {
                 // [capture] coroutine, onCatch, timing
                 parentScreen.Initialized += p => StartCoroutine(new CoroutineState(p), DummyState.Null, coroutine, onCatch, timing).Forget();
             }
             return;
         }
         else
         {
             if (onCatch is null)
             {
                 // [capture] state, coroutine, timing
                 parentScreen.Initialized += p => StartCoroutine(new CoroutineState(p), state, coroutine, null, timing).Forget();
             }
             else
             {
                 // [capture] state, coroutine, onCatch, timing
                 parentScreen.Initialized += p => StartCoroutine(new CoroutineState(p), state, coroutine, onCatch, timing).Forget();
             }
             return;
         }
     }
     else if (typeof(TParent) == typeof(FrameObject))
     {
         var parentFrameObject = SafeCast.As <FrameObject>(parent);
         if (typeof(TState) == typeof(DummyState))
         {
             if (onCatch is null)
             {
                 // [capture] coroutine, timing
                 parentFrameObject.Alive += f => StartCoroutine(new CoroutineState(f), DummyState.Null, coroutine, null, timing).Forget();
             }
             else
             {
                 // [capture] coroutine, onCatch, timing
                 parentFrameObject.Alive += f => StartCoroutine(new CoroutineState(f), DummyState.Null, coroutine, onCatch, timing).Forget();
             }
             return;
         }
         else
         {
             if (onCatch is null)
             {
                 // [capture] state, coroutine, timing
                 parentFrameObject.Alive += f => StartCoroutine(new CoroutineState(f), state, coroutine, null, timing).Forget();
             }
             else
             {
                 // [capture] state, coroutine, onCatch, timing
                 parentFrameObject.Alive += f => StartCoroutine(new CoroutineState(f), state, coroutine, onCatch, timing).Forget();
             }
             return;
         }
     }
     else
     {
         Debug.Fail("Something wrong");
         return;
     }
 }