#c# #generics
#c# #общие
Вопрос:
Мне нужно написать общий метод расширения List<T>
, который условно учитывает несколько Textbox
значений (10 из них), чтобы увидеть, не превышает ли каждое из них 25, а затем Sum
другой набор Textbox
значений, если условие выполнено.
то же, SUMIF
что и в Microsoft Excel, где (диапазон (массив текстового поля1), критерии (=<25), сумма диапазона (массив текстового поля2). =SUMIF(F7,»<=25″, I10) SUMIF(L13, «<=25»,L20)
Я использовал следующий код из другого потока, я просто не знаю, как это реализовать одним нажатием кнопки.
public static double SumIf<T>(
IEnumerable<T> source,
Func<T, double > textSelector,
Func<T, double> valueSelector)
{
return source.Where(x => textSelector(x) <= 25.5).Sum(valueSelector);
}
Комментарии:
1. Немного неясно, о чем вы спрашиваете (по крайней мере, для меня) в отношении 2 списков
2. Что вы имеете в виду? Конечно, вы бы вызвали
SumIf
из обработчика нажатия кнопки?3. Это приложение WPF?
4. Есть ли какие-либо случаи, когда
textSelector
valueSelector
ожидается, что и будут разными? Если нет, выsource.Select(textSelector).Where(x => x <= 25.5).Sum();
также должны сделать, для чегоtargetText
используется?5. На самом деле неясно, в чем заключается ваша проблема. Добавьте кнопку, добавьте событие при «щелчке», напишите код для передачи значений из ваших текстовых полей в этот метод и т.д. Обратите внимание, что мое предложение все еще очень общее, потому что мы не знаем, какую среду пользовательского интерфейса вы используете (WinForms, WPF, WebForms, MVC и т. Д.) Или Где проблема в реализации.
Ответ №1:
Предлагаемый SumIf
вами метод немного неудобен для ваших целей.
Давайте предположим, что вам удалось определить два массива текстовых полей — первый набор, который вы проверяете, если значение меньше 25, а другой, который вы хотите суммировать:
TextBox[] firstTextBoxes = ...;
TextBox[] otherTextBoxes = ...;
Теперь, чтобы я мог использовать ваш существующий SumIf
метод, мне нужно вызвать его следующим образом:
double result =
Ex.SumIf(
firstTextBoxes.Zip(otherTextBoxes, (first, other) => new { first, other }),
x => double.Parse(x.first.Text),
x => double.Parse(x.other.Text));
Zip
Пары текстовых полей, а затем вы можете вызвать SumIf
парный список.
Способ написания кода просто скрывает часть логики внутри SumIf
, и остается очень мало интересного кода, чтобы рассказать вам, что происходит.
Ваш код трудно понять.
Один из подходов заключается в том, чтобы изменить SumIf
SumOtherIfFirstLessThanEqual25
его следующим образом:
public static double SumOtherIfFirstLessThanEqual25(IEnumerable<(TextBox first, TextBox other)> source)
{
return source.Where(x => double.Parse(x.first.Text) <= 25.0).Sum(x => double.Parse(x.other.Text));
}
Теперь вы можете написать:
double result =
Ex.SumOtherIfFirstLessThanEqual25(
firstTextBoxes.Zip(otherTextBoxes, (first, other) => (first, other)));
Теперь, если вы перейдете SumOtherIfFirstLessThanEqual25
к методу расширения:
public static class Ex
{
public static double SumOtherIfFirstLessThanEqual25(this IEnumerable<(TextBox first, TextBox other)> source)
{
return source.Where(x => double.Parse(x.first.Text) <= 25.0).Sum(x => double.Parse(x.other.Text));
}
}
…вы можете написать это:
double result =
firstTextBoxes
.Zip(otherTextBoxes, (first, other) => (first, other))
.SumOtherIfFirstLessThanEqual25();
Это читаемо, и вы можете понять, что происходит.
Однако лучше придерживаться более стандартного подхода.
Вы могли бы написать свой SumIf
метод следующим образом:
public static class Ex
{
public static double SumIf<T>(this IEnumerable<T> source,
Func<T, bool> filter,
Func<T, double> selector)
{
return source.Where(x => filter(x)).Sum(selector);
}
}
Теперь вы можете написать это:
double result =
Ex1.SumIf(
firstTextBoxes.Zip(otherTextBoxes, (tb, otb) => new { tb, otb }),
x => double.Parse(x.tb.Text) <= 25.0,
x => double.Parse(x.otb.Text));
Это лучше и, как правило, содержит всю логику в нужном месте. Но это все равно можно улучшить, если вы полностью избавитесь от SumIf
метода.
Попробуйте это:
double result =
firstTextBoxes
.Zip(otherTextBoxes, (tb, otb) => new { tb, otb })
.Where(x => double.Parse(x.tb.Text) <= 25.0)
.Sum(x => double.Parse(x.otb.Text));
Это имеет все те же функциональные возможности, но логика построена с использованием стандартных операторов LINQ, и она четко пошаговая и легко читается.
Теперь вам просто нужно написать это:
private void button1_Click(object sender, EventArgs e)
{
TextBox[] firstTextBoxes = /* populate your first array here */;
TextBox[] otherTextBoxes = /* populate your other array here */;
double result =
firstTextBoxes
.Zip(otherTextBoxes, (tb, otb) => new { tb, otb })
.Where(x => double.Parse(x.tb.Text) <= 25.0)
.Sum(x => double.Parse(x.otb.Text));
//do something with `result` here
}
Комментарии:
1. это именно то, чего я ожидал в результате, теперь это более понятно, большое спасибо за введение другого метода и извините за неясность