Generic остановить цепочку вызовов.
От: #John Европа https://github.com/ichensky
Дата: 29.05.17 15:48
Оценка:
Здравствуйте,
А можно ли как-то остановить цепочку вызовов методов `go`?:
 public class value
    {
        public int x;
    }
    public class b
    {
        public value value;

    }
    public static class a
    {
        public static b go(this b model, int x)
        {

            if (model.value == null && x == 5)
            {
                model.value = new value { x = x };
            }

            return model;
        }
    }

    public class Program
    {
        public static void Main()
        {
            // где-то в коде
            var b = new b();
            var o = b
                .go(4)
                .go(5) // Если в `model` есть какой-то объект, 
                       // дальше `go` не должны вызываться, а вернуть `model` объект
                .go(10)
                .go(20)
                ;
        }
    }
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re: Generic остановить цепочку вызовов.
От: Nikolay_Ch Россия  
Дата: 29.05.17 18:28
Оценка:
Здравствуйте, #John, Вы писали:

J>Здравствуйте,

J>А можно ли как-то остановить цепочку вызовов методов `go`?:
А позвольте поинтересоваться целью?
Re: Generic остановить цепочку вызовов.
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.05.17 18:44
Оценка:
Здравствуйте, #John, Вы писали:

J>Здравствуйте,

J>А можно ли как-то остановить цепочку вызовов методов `go`?:
Метод не может принимать решение о том, будет ли после нормального (не исключительного) завершения текущего метода вызван метод, следующий за ним безусловно.
Т.е. остановить можно, с помощью исключения. Но и возврата тогда не будет.
Re[2]: Generic остановить цепочку вызовов.
От: Nikolay_Ch Россия  
Дата: 29.05.17 18:47
Оценка:
Здравствуйте, samius, Вы писали:

J>>А можно ли как-то остановить цепочку вызовов методов `go`?:

S>Метод не может принимать решение о том, будет ли после нормального (не исключительного) завершения текущего метода вызван метод, следующий за ним безусловно.
S>Т.е. остановить можно, с помощью исключения. Но и возврата тогда не будет.
Можно не останавливать, а возвращать из метода объект, у которого вызов метода go будет возвращать самого себя...
Re[2]: Generic остановить цепочку вызовов.
От: #John Европа https://github.com/ichensky
Дата: 29.05.17 19:16
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Здравствуйте, #John, Вы писали:


J>>Здравствуйте,

J>>А можно ли как-то остановить цепочку вызовов методов `go`?:
N_C>А позвольте поинтересоваться целью?
Мне нужен метод, в который я запихиваю какие-то данные, в методе они проверяются, если все оК, то в зависимости от тех данных, которые закинул в метод, будет создан этот объект(мы еще одним параметром можем передать делегат Func<object> который создаст объект). И этот объект, функция должна вернуть.
Можно считать что нужна функция как аналог куче if else инструкций, где проверяются какие-то данные, а потом создается нужный объект. и вот что бы писать меньше кода и код был читабельние все это дело можно завернуть в код как выше.
Да, может if-else будет работать быстрее, чем прокидывать Func как параметр, и вместо выполнения одной инструкции if-else идет вызов метода, но тот участок кода не нуждается в такой сверх оптимизации, однако то, что после того как создан объект `value` идет еще куча вызовов `go` с проверками на null, это смущает. По идее их можно было бы избежать.

if(x==typeof(y)){
    obj=new y1(z,..);
} else if(x==typeof(w)){
    obj=new y2(h,u..);
} else if(x==typeof(k)){
    obj=new y3(t..);
}
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[3]: Generic остановить цепочку вызовов.
От: Nikolay_Ch Россия  
Дата: 29.05.17 19:23
Оценка:
Здравствуйте, #John, Вы писали:

J>Мне нужен метод, в который я запихиваю какие-то данные, в методе они проверяются, если все оК, то в зависимости от тех данных, которые закинул в метод, будет создан этот объект(мы еще одним параметром можем передать делегат Func<object> который создаст объект). И этот объект, функция должна вернуть.

Ну так и что мешает вернуть объект, который будет вместо проверки возвращать дальше самого себя?... Ну, или объект, у которого стоит флаг, из-за которого он не проверяет входные параметры, а возвращает самого себя. Тогда внутри метода достаточно будет создать объект и взвести для него этот флаг.
Остановить цепочку вызовов Вы не остановите, но они в итоге будут пустые — вроде, Вашу задачу это решает, пусть и не оптимальным способом.
Отредактировано 29.05.2017 19:23 Nikolay_Ch . Предыдущая версия .
Re: Generic остановить цепочку вызовов.
От: Sinatr Германия  
Дата: 30.05.17 07:11
Оценка:
Здравствуйте, #John, Вы писали:

J>А можно ли как-то остановить цепочку вызовов методов `go`?:


Да, используя ?. оператор, если вернуть null для цепочики вызовов b.go(4)?.go(5)?.go(10)...

Ну или как уже сказали ранее, можно предусмотреть особый случай (специальное значение, тот же null, или значение члена, к примеру model.value.x == int.MaxInt), чтобы "игнорировать" последующие вызовы и просто возвращать b.
---
ПроГLамеры объединяйтесь..
Re[3]: Generic остановить цепочку вызовов.
От: yenik  
Дата: 30.05.17 08:31
Оценка:
J>участок кода не нуждается в такой сверх оптимизации... идет еще куча вызовов `go` с проверками на null, это смущает.

В этой фразе есть какое-то противоречие. Или оптимизируем, или не оптимизируем.
Re[2]: Generic остановить цепочку вызовов.
От: rameel https://github.com/rsdn/CodeJam
Дата: 30.05.17 08:35
Оценка:
Здравствуйте, Sinatr, Вы писали:

S>Здравствуйте, #John, Вы писали:


S>Да, используя ?. оператор, если вернуть null для цепочики вызовов b.go(4)?.go(5)?.go(10)...


Для топикстартера как раз таки null не нужен
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re: Generic остановить цепочку вызовов.
От: kov_serg Россия  
Дата: 30.05.17 09:48
Оценка:
Здравствуйте, #John, Вы писали:

J>Здравствуйте,

J>А можно ли как-то остановить цепочку вызовов методов `go`?:
using System;

public class A {
    public int x;
}
public static class Aext {
    class EA : Exception { public A a; }
    public static A go(this A a,int x) {
        Console.WriteLine("x={0}",x);
        if (x == 3) throw new EA() { a = a };
        Console.WriteLine("create new A(x={0})",a.x);
        a = new A() { x = x };
        return a;
    }
    public static A run(this A a, Func<A> f) {
        try { return f(); } catch (EA e) { return e.a; }
    }
}

class Test {
    static void Main(string[] args) {
        var a = new A() { x = 0 };

        var o=a.run(() => a
            .go(1)
            .go(2)
            .go(3)
            .go(4)
        );

        Console.WriteLine("o.x={0}",o.x);
    }
}

x=1
create new A(x=1)
x=2
create new A(x=2)
x=3
o.x=2

Так не катит?
Re[3]: Generic остановить цепочку вызовов.
От: Vladek Россия Github
Дата: 30.05.17 10:50
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Здравствуйте, samius, Вы писали:


J>>>А можно ли как-то остановить цепочку вызовов методов `go`?:

S>>Метод не может принимать решение о том, будет ли после нормального (не исключительного) завершения текущего метода вызван метод, следующий за ним безусловно.
S>>Т.е. остановить можно, с помощью исключения. Но и возврата тогда не будет.
N_C>Можно не останавливать, а возвращать из метода объект, у которого вызов метода go будет возвращать самого себя...

https://sourcemaking.com/design_patterns/null_object
Re[3]: Generic остановить цепочку вызовов.
От: #John Европа https://github.com/ichensky
Дата: 30.05.17 11:41
Оценка:
Здравствуйте, rameel, Вы писали:

R>Здравствуйте, Sinatr, Вы писали:


S>>Здравствуйте, #John, Вы писали:


S>>Да, используя ?. оператор, если вернуть null для цепочики вызовов b.go(4)?.go(5)?.go(10)...


R>Для топикстартера как раз таки null не нужен

Да, потому что, чтобы прервать цепочку вызовов надо будет из функции вернуть null. А нам нужен объект, а не null, потому придется еще как параметр передавать в функцию еще какой-то объект в которой будет сохраняться значение.
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[2]: Generic остановить цепочку вызовов.
От: #John Европа https://github.com/ichensky
Дата: 30.05.17 11:46
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Так не катит?

Как один из вариантов решения норм., тоже первое что пришло в голову. Но, не нравится это решение тем что, когда срабатывает Exception, сохраняется call stack, создается куча лишних структур и происходит куча дополнительных проверок.
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[4]: Generic остановить цепочку вызовов.
От: #John Европа https://github.com/ichensky
Дата: 30.05.17 12:00
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Здравствуйте, #John, Вы писали:


J>>Мне нужен метод, в который я запихиваю какие-то данные, в методе они проверяются, если все оК, то в зависимости от тех данных, которые закинул в метод, будет создан этот объект(мы еще одним параметром можем передать делегат Func<object> который создаст объект). И этот объект, функция должна вернуть.

N_C>Ну так и что мешает вернуть объект, который будет вместо проверки возвращать дальше самого себя?... Ну, или объект, у которого стоит флаг, из-за которого он не проверяет входные параметры, а возвращает самого себя. Тогда внутри метода достаточно будет создать объект и взвести для него этот флаг.
N_C>Остановить цепочку вызовов Вы не остановите, но они в итоге будут пустые — вроде, Вашу задачу это решает, пусть и не оптимальным способом.

Да, спасибо. Так лучше всего работает.
 public class value
    {
        public int x;
    }
    public class b
    {
        public value value;

    }

    public class f {
        public int x;
    }
    public class c {
        public value go(params f[] f) {
            foreach (var item in f)
            {
                if (item.x==5)
                {
                    return new value { x = item.x };
                }
            }
            return null;
        }
    }
     public class Program
    {
        public static void Main()
        {
            var c = new c();
            var o = c.go(
                new f { x=4 }, 
                new f { x = 5 }, 
                new f { x = 10 },
                new f { x = 20 });           
        }
    }
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[2]: Generic остановить цепочку вызовов.
От: yenik  
Дата: 30.05.17 14:16
Оценка: +3
_> public static A run(this A a, Func<A> f) {
_> try { return f(); } catch (EA e) { return e.a; }
_> }

Авторитеты не советуют.

X DO NOT use exceptions for the normal flow of control, if possible.


Framework Design Guidelines
Re[5]: Generic остановить цепочку вызовов.
От: Sinix  
Дата: 31.05.17 06:58
Оценка: 2 (1)
Здравствуйте, #John, Вы писали:

J>>>Мне нужен метод, в который я запихиваю какие-то данные, в методе они проверяются, если все оК, то в зависимости от тех данных, которые закинул в метод, будет создан этот объект(мы еще одним параметром можем передать делегат Func<object> который создаст объект). И этот объект, функция должна вернуть.


Ну и пишем сценарий использования:
var candidates = ...
var result = MyType.TryCreate(candidates);

или, если логика создания произвольная —
var arg = candidates.FirstOrDefault(x => ...);
if (arg != null)
{
  ...
}
else
{
  var result = CreateMyType(arg, ...);
}

Какие ещё варианты-то? Тов. yenik правильно пишет, FDG читать надо

P.S. И соглашения по именованию тоже соблюдать надо
Re: Generic остановить цепочку вызовов.
От: TK Лес кывт.рф
Дата: 31.05.17 08:48
Оценка:
Здравствуйте, #John, Вы писали:

J>Здравствуйте,

J>А можно ли как-то остановить цепочку вызовов методов `go`?:

Просто сделайте foreach по массиву входных данных — будет вам и прерывание в любой момент и даже, при желании, возврат назад
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Generic остановить цепочку вызовов.
От: LWhisper  
Дата: 01.06.17 07:37
Оценка:
Автор, ты описываешь конечный автомат.
Красивый, быстрый и понятный механизм ты можешь описать самостоятельно, но пока у тебя ничтожно мало состояний он будет проигрывать конструкции с if/return.
В топорном варианте, используя сахар C#, его можно описать так:

    public class Program
    {
        public static void Main()
        {
            // где-то в коде
            var b = new b();
            var o = ProcessStrangeAlg(b);
        }

        private static b ProcessStrangeAlg(b model)
        {
            return StrangeAlg(model).LastOrDefault();
        }

        private static IEnumerable<b> StrangeAlg(b model)
        {
            foreach (var value in new[] {4, 5, 10, 20})
            {
                model = model.go(value);
                yield return model;

                if (model.value != null)
                    yield break;
            }
        }
    }


Если работа с промежуточным состоянием не требуется, то у тебя просто конвейер действий, который ты можешь инициализировать хоть параметрами, хоть делегатами, хоть фабриками:

private static b ProcessStrangeAlg(b model)
        {
            foreach (var value in new[] { 4, 5, 10, 20 })
            {
                model = model.go(value);
                if (model.value != null)
                    return model;
            }

            return null;
        }
Отредактировано 01.06.2017 7:44 LWhisper . Предыдущая версия .
Re: Generic остановить цепочку вызовов.
От: Doc Россия http://andrey.moveax.ru
Дата: 03.06.17 02:43
Оценка:
Здравствуйте, #John, Вы писали:

J>А можно ли как-то остановить цепочку вызовов методов `go`?:


Мне кажется вы с помощью fluent интерфейса пытаетесь реализовать конвейер (он же Chain of Responsibility)
Реализуйте этот шаблон, а не прикручивайте костыли к fluent.

Пример реализации
http://andrey.moveax.ru/post/patterns-oop-behavioral-chain-of-responsibility
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.