Здравствуйте,
А можно ли как-то остановить цепочку вызовов методов `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)
;
}
}
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, #John, Вы писали:
J>Здравствуйте, J>А можно ли как-то остановить цепочку вызовов методов `go`?:
Метод не может принимать решение о том, будет ли после нормального (не исключительного) завершения текущего метода вызван метод, следующий за ним безусловно.
Т.е. остановить можно, с помощью исключения. Но и возврата тогда не будет.
Здравствуйте, samius, Вы писали:
J>>А можно ли как-то остановить цепочку вызовов методов `go`?: S>Метод не может принимать решение о том, будет ли после нормального (не исключительного) завершения текущего метода вызван метод, следующий за ним безусловно. S>Т.е. остановить можно, с помощью исключения. Но и возврата тогда не будет.
Можно не останавливать, а возвращать из метода объект, у которого вызов метода go будет возвращать самого себя...
Здравствуйте, Nikolay_Ch, Вы писали:
N_C>Здравствуйте, #John, Вы писали:
J>>Здравствуйте, J>>А можно ли как-то остановить цепочку вызовов методов `go`?: N_C>А позвольте поинтересоваться целью?
Мне нужен метод, в который я запихиваю какие-то данные, в методе они проверяются, если все оК, то в зависимости от тех данных, которые закинул в метод, будет создан этот объект(мы еще одним параметром можем передать делегат Func<object> который создаст объект). И этот объект, функция должна вернуть.
Можно считать что нужна функция как аналог куче if else инструкций, где проверяются какие-то данные, а потом создается нужный объект. и вот что бы писать меньше кода и код был читабельние все это дело можно завернуть в код как выше.
Да, может if-else будет работать быстрее, чем прокидывать Func как параметр, и вместо выполнения одной инструкции if-else идет вызов метода, но тот участок кода не нуждается в такой сверх оптимизации, однако то, что после того как создан объект `value` идет еще куча вызовов `go` с проверками на null, это смущает. По идее их можно было бы избежать.
Здравствуйте, #John, Вы писали:
J>Мне нужен метод, в который я запихиваю какие-то данные, в методе они проверяются, если все оК, то в зависимости от тех данных, которые закинул в метод, будет создан этот объект(мы еще одним параметром можем передать делегат Func<object> который создаст объект). И этот объект, функция должна вернуть.
Ну так и что мешает вернуть объект, который будет вместо проверки возвращать дальше самого себя?... Ну, или объект, у которого стоит флаг, из-за которого он не проверяет входные параметры, а возвращает самого себя. Тогда внутри метода достаточно будет создать объект и взвести для него этот флаг.
Остановить цепочку вызовов Вы не остановите, но они в итоге будут пустые — вроде, Вашу задачу это решает, пусть и не оптимальным способом.
Здравствуйте, #John, Вы писали:
J>А можно ли как-то остановить цепочку вызовов методов `go`?:
Да, используя ?. оператор, если вернуть null для цепочики вызовов b.go(4)?.go(5)?.go(10)...
Ну или как уже сказали ранее, можно предусмотреть особый случай (специальное значение, тот же null, или значение члена, к примеру model.value.x == int.MaxInt), чтобы "игнорировать" последующие вызовы и просто возвращать b.
Здравствуйте, Sinatr, Вы писали:
S>Здравствуйте, #John, Вы писали:
S>Да, используя ?. оператор, если вернуть null для цепочики вызовов b.go(4)?.go(5)?.go(10)...
Здравствуйте, #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
Здравствуйте, Nikolay_Ch, Вы писали:
N_C>Здравствуйте, samius, Вы писали:
J>>>А можно ли как-то остановить цепочку вызовов методов `go`?: S>>Метод не может принимать решение о том, будет ли после нормального (не исключительного) завершения текущего метода вызван метод, следующий за ним безусловно. S>>Т.е. остановить можно, с помощью исключения. Но и возврата тогда не будет. N_C>Можно не останавливать, а возвращать из метода объект, у которого вызов метода go будет возвращать самого себя...
Здравствуйте, rameel, Вы писали:
R>Здравствуйте, Sinatr, Вы писали:
S>>Здравствуйте, #John, Вы писали:
S>>Да, используя ?. оператор, если вернуть null для цепочики вызовов b.go(4)?.go(5)?.go(10)...
R>Для топикстартера как раз таки null не нужен
Да, потому что, чтобы прервать цепочку вызовов надо будет из функции вернуть null. А нам нужен объект, а не null, потому придется еще как параметр передавать в функцию еще какой-то объект в которой будет сохраняться значение.
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, kov_serg, Вы писали:
_>Так не катит?
Как один из вариантов решения норм., тоже первое что пришло в голову. Но, не нравится это решение тем что, когда срабатывает Exception, сохраняется call stack, создается куча лишних структур и происходит куча дополнительных проверок.
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, 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 });
}
}
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, #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. И соглашения по именованию тоже соблюдать надо
Автор, ты описываешь конечный автомат.
Красивый, быстрый и понятный механизм ты можешь описать самостоятельно, но пока у тебя ничтожно мало состояний он будет проигрывать конструкции с 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;
}
Здравствуйте, #John, Вы писали:
J>А можно ли как-то остановить цепочку вызовов методов `go`?:
Мне кажется вы с помощью fluent интерфейса пытаетесь реализовать конвейер (он же Chain of Responsibility)
Реализуйте этот шаблон, а не прикручивайте костыли к fluent.