Иногда результатом работы метода являются два значения, причем первое всегда используется вызывающим кодом, второе — только в некоторых случаях. Это второе значение можно сделать невидимым для кода, которому оно не нужно, поместив оба значения-результата в struct и определив операцию неявного преобразования к типу первого значения:
struct FResult {
public int Required { get; private set; }
public int Optional { get; private set; }
public FResult(int required, int optional)
: this() { Required = required; Optional = optional; }
public static implicit operator int(FResult result) {
return result.Required;
}
}
FResult F() {
. . .
return new FResult( . . .
}
void G() {
int i = F();
. . .
}
void H() {
FResult r = F();
int i = r.Required;
int j = r.Optional;
. . .
}
Здравствуйте, igna, Вы писали:
I>Иногда результатом работы метода являются два значения, причем первое всегда используется вызывающим кодом, второе — только в некоторых случаях. Это второе значение можно сделать невидимым для кода, которому оно не нужно, поместив оба значения-результата в struct и определив операцию неявного преобразования к типу первого значения: I>Возражения принимаются.
Ну самое очевидное возражение — как понять, есть ли опциональное значение или нет? Т.е. тут нужен по кр. мере nullable-тип или какой-нибудь флажок.
Потом — бывает ли у метода такая ситуация, что запрашиваемое действие выполнить невозможно? Т.е. и обязательного параметра не будет?
Потом это, конечно, все зависит от прикладной задачи — т.е. насколько необходима именно структура — ну вот мне какой-то такой вариант как-то больше нравится:
public class Result
{
public Status Status { get; private set; }
}
public sealed class SimpleResult : Result
{
public int SomeValue { get; }
}
public sealed class ComplexResult : Result
{
public int SomeValue { get; }
public int AnotherValue { get; }
}
Здравствуйте, igna, Вы писали:
I>Иногда результатом работы метода являются два значения, причем первое всегда используется вызывающим кодом, второе — только в некоторых случаях. Это второе значение можно сделать невидимым для кода, которому оно не нужно, поместив оба значения-результата в struct и определив операцию неявного преобразования к типу первого значения:
Сделайте два метода — один который возвращает нужные объекты, а другой ненужные. Вызывающий код должен явно выражать свои намерения.
Ситуаций когда вызываемый код неявно пытается подстроиться под вызывающий лучше не допускать — если развивать данное направление, то легко дойти до маразмов...
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, igna, Вы писали: I>Именно так, или "два метода — один который возвращает нужные объекты, а другой нужные и ненужные"?
Ну, в общем случае, наверное, лучше твой вариант — чтобы избежать двукратного вызова для запроса дополнительных данных.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Ну, в общем случае, наверное, лучше твой вариант — чтобы избежать двукратного вызова для запроса дополнительных данных.
Я спрашивал, не как лучше, а что он имел в виду. Возможно, именно "мой" вариант, просто написал, как написал.
Здравствуйте, igna, Вы писали:
S>>Ну, в общем случае, наверное, лучше твой вариант — чтобы избежать двукратного вызова для запроса дополнительных данных. I>Я спрашивал, не как лучше, а что он имел в виду. Возможно, именно "мой" вариант, просто написал, как написал.
Это просто "фигура речи". Если данные "не нужные" то и возвращать их вообще не надо.
Если же предполагается, что основные и доп. данные как-то между собой связаны и получение их "дешево" то, объедините их в сруктуру и возвращайте ее без всяких "неявных" преобразований. Если вруг захочется неявности на вызывающей стороне то, можно там писать var required = o.GetDataStruct().Required;
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, ylem, Вы писали:
Y>out параметр для значение, которое получается всегда и nullable тип результата для значения, которое не всегда -- сильно просто?
Здравствуйте, TK, Вы писали:
TK>Если же предполагается, что основные и доп. данные как-то между собой связаны и получение их "дешево" то, объедините их в сруктуру и возвращайте ее без всяких "неявных" преобразований. Если вруг захочется неявности на вызывающей стороне то, можно там писать var required = o.GetDataStruct().Required;
Возможно. В смысле, может быть лучше 100 раз написать
var required = o.GetDataStruct().Required;
, чем 100 раз
var required = o.GetDataStruct();
и один раз
public static implicit operator int(FResult result) {
return result.Required;
}
Но не обязательно. Кроме того второй вариант дает возможность в новой версии добавить к результату опциональное значение не меняя вызывающего кода во всей программе.
Здравствуйте, igna, Вы писали:
I>Но не обязательно. Кроме того второй вариант дает возможность в новой версии добавить к результату опциональное значение не меняя вызывающего кода во всей программе.
Зачем нужно опциональное значение которое, никем не используется... тем более, по всей программе?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>Здравствуйте, igna, Вы писали:
I>>Но не обязательно. Кроме того второй вариант дает возможность в новой версии добавить к результату опциональное значение не меняя вызывающего кода во всей программе.
TK>Зачем нужно опциональное значение которое, никем не используется... тем более, по всей программе?
Используется, но, скажем, 10 раз. А 100 раз не используется.
Здравствуйте, igna, Вы писали:
TK>>Зачем нужно опциональное значение которое, никем не используется... тем более, по всей программе? I>Используется, но, скажем, 10 раз. А 100 раз не используется.
Где у вас гарантия, что в случае неявного преобразования оно не начнет использоваться "неправильно" или не так, как ждали?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>>>Зачем нужно опциональное значение которое, никем не используется... тем более, по всей программе? I>>Используется, но, скажем, 10 раз. А 100 раз не используется.
TK>Где у вас гарантия, что в случае неявного преобразования оно не начнет использоваться "неправильно" или не так, как ждали?
Здравствуйте, igna, Вы писали:
TK>>Где у вас гарантия, что в случае неявного преобразования оно не начнет использоваться "неправильно" или не так, как ждали? I>Что "оно"? Опциональное значение?
Не опциональное значение, а замена int на "чудо структуру" с неявным поведением.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>>>Где у вас гарантия, что в случае неявного преобразования оно не начнет использоваться "неправильно" или не так, как ждали? I>>Что "оно"? Опциональное значение?
TK>Не опциональное значение, а замена int на "чудо структуру" с неявным поведением.
Здравствуйте, igna, Вы писали:
I>Иногда результатом работы метода являются два значения, причем первое всегда используется вызывающим кодом, второе — только в некоторых случаях. Это второе значение можно сделать невидимым для кода, которому оно не нужно, поместив оба значения-результата в struct и определив операцию неявного преобразования к типу первого значения:
I>
I>struct FResult {
I> public int Required { get; private set; }
I> public int Optional { get; private set; }
I> public FResult(int required, int optional)
I> : this() { Required = required; Optional = optional; }
I> public static implicit operator int(FResult result) {
I> return result.Required;
I> }
I>}
I>FResult F() {
I> . . .
I> return new FResult( . . .
I>}
I>void G() {
I> int i = F();
I> . . .
I>}
I>void H() {
I> FResult r = F();
I> int i = r.Required;
I> int j = r.Optional;
I> . . .
I>}
I>
I>Возражения принимаются.
1) Преобразование типов используется не по назначению.
Нет механизма преобразования int к FResult.
Преобразование FResult к int не будет поддерживать транзитивность, тобишь FResult >> int >> NewFResult и имеем FResult <> NewFResult в случаи,
если нужно использовать свойство — Optional.
2) Логика по принятию решения, нужно использовать Optional или не нужно должна быть реализована за пределами класса F и результатов которые он возвращает.
Не стоит "косвенно" и "неявно" засунуть эту логику в FResult, это не его обязанности.
Вернёт метод 2 значения и что в этом такого, тот кто получил эти значения должен знать как с ними работать.
3) Сдаётся, что пахнет полиморфизмом.
Трудно что то конкретное подсказать, нужна более детальная инфа о пред. области.
Вопросы аля в одном слчаи должен в другом нет >> явный намёк на полифорфизм.
Здравствуйте, igna, Вы писали:
TK>>Не опциональное значение, а замена int на "чудо структуру" с неявным поведением. I>Например? Как неправильно?
Я тут вижу, что про ToString() в своей структуре вы забыли.
Следовательно, код String.Format(..., o.GetDataStruct()) будет работать "по другому". И это только начало
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Y>>out параметр для значение, которое получается всегда и nullable тип результата для значения, которое не всегда -- сильно просто?
I>nullable тут вообще не причем.
Ну ладно.
Но это, имхо, самый простой и, вроде бы, последовательный способ изобразить, что ЗНАЧЕНИЯ нет.
разве нет?
Здравствуйте, ylem, Вы писали:
Y>Ну ладно. Y>Но это, имхо, самый простой и, вроде бы, последовательный способ изобразить, что ЗНАЧЕНИЯ нет. Y>разве нет?
Дело в том, что изображать, что значения нет, не надо, значение всегда есть. Опциональное оно не в том смысле, что то ли вычисляется вызываемым кодом, то ли нет; а в том, что оно то используется вызывающим кодом, то нет.