В моем коде, у меня есть большое количество классов, которые нужно выполнять различные коллективные операции на своих членов, чтобы получить результаты (среднее, стандартное отклонение, доверительные интервалы и т.д.)Делегат для LINQ расширений
Average
LINQ расширения метод уже существует, но StandardDeviation
не делает, поэтому я реализовал это следующим образом:
public static double StandardDeviation<T>(this IEnumerable<T> source, Func<T, double> selector)
{
var average = source.Average(selector);
var sumOfSquares = source.Sum(sample => Math.Pow(selector(sample) - average, 2));
return Math.Pow(sumOfSquares, 0.5);
}
Я хотел бы найти способ определения делегата для этой функции, в идеале в качестве расширения LINQ, чтобы избежать дублирования кода. Ниже приведен пример текущего использования двух методов:
public override void Average(IList<ThisType> samples)
{
TotalEntered = samples.Average(sample => sample.TotalEntered);
TotalExited = samples.Average(sample => sample.TotalExited);
MinimumContents = samples.Average(sample => sample.MinimumContents);
AverageContents = samples.Average(sample => sample.AverageContents);
MaximumContents = samples.Average(sample => sample.MaximumContents);
MinimumTime = samples.Average(sample => sample.MinimumTime);
AverageTime = samples.Average(sample => sample.AverageTime);
MaximumTime = samples.Average(sample => sample.MaximumTime);
StdDevTime = samples.Average(sample => sample.StdDevTime);
AverageNonZeroTime = samples.Average(sample => sample.AverageNonZeroTime);
PercentageWithinLimit = samples.Average(sample => sample.PercentageWithinLimit);
base.Average(samples);
}
public override void StandardDeviation(IList<ThisType> samples)
{
TotalEntered = samples.StandardDeviation(sample => sample.TotalEntered);
TotalExited = samples.StandardDeviation(sample => sample.TotalExited);
MinimumContents = samples.StandardDeviation(sample => sample.MinimumContents);
AverageContents = samples.StandardDeviation(sample => sample.AverageContents);
MaximumContents = samples.StandardDeviation(sample => sample.MaximumContents);
MinimumTime = samples.StandardDeviation(sample => sample.MinimumTime);
AverageTime = samples.StandardDeviation(sample => sample.AverageTime);
MaximumTime = samples.StandardDeviation(sample => sample.MaximumTime);
StdDevTime = samples.StandardDeviation(sample => sample.StdDevTime);
AverageNonZeroTime = samples.StandardDeviation(sample => sample.AverageNonZeroTime);
PercentageWithinLimit = queueSamples.StandardDeviation(sample => sample.PercentageWithinLimit);
base.StandardDeviation(samples);
}
Я попытался создать делегат для этих методов, а именно:
public delegate double CollectiveOperation<T>(IEnumerable<T> source, Func<T, double> selector);
Для использования в следующей замене для выше вблизи -duplication кода:
public void Operation(IList<ThisType> samples, LINQExtensions.CollectiveOperation<ThisType> Operation)
{
BufferMinimumTime = samples.Operation(sample => sample.BufferMinimumTime);
BufferAverageTime = samples.Operation(sample => sample.BufferAverageTime);
BufferMaximumTime = samples.Operation(sample => sample.BufferMaximumTime);
BufferStdDevTime = samples.Operation(sample => sample.BufferStdDevTime);
TotalMinimumTime = samples.Operation(sample => sample.TotalMinimumTime);
TotalAverageTime = samples.Operation(sample => sample.TotalAverageTime);
TotalMaximumTime = samples.Operation(sample => sample.TotalMaximumTime);
TotalStdDevTime = samples.Operation(sample => sample.TotalStdDevTime);
base.Operation(samples);
}
Однако, я не был в состоянии назвать Average
или StandardDeviation
через эти делегаты, предположительно из-за this
ключевое слово. После удаления этого из StandardDeviation
реализации и замена вызовов с чем-то вроде:
BufferMinimumTime = Operation(samples, sample => sample.BufferMinimumTime);
Он по-прежнему не будет соответствовать с делегатом, производя следующее сообщение об ошибке:
Expected a method with 'double StandardDeviation(IEnumerable<ThisType>, Func<ThisType, double>)' signature.
Есть ли способ для мне создать делегат для общего статического расширения LINQ, как указано выше? Эти методы будут использоваться в различных классах уникальными способами, поэтому они должны быть общими.
Мне удалось заставить это работать с вашими определениями 'CollectiveOperation' и 'StandardDeviation ', Stock 'Enumerable.Average ' и небольшой тестовый класс для 'T'. Можете ли вы сконденсировать свой вопрос на примере с минимальным количеством кода, необходимым для воспроизведения проблемы? –
Rawling
сначала ваше расширение StandardDeviation должно использовать возврат доходности, а не полный возврат коллекции, посмотрите на это в Интернете. Во-вторых, вы можете использовать отражение и получить список членов в образце, где имя соответствует локальному члену, а затем вызвать средний метод, присваивающий результат локальному члену. – Franck
@Franck Как может 'StandardDeviation' использовать' yield return', когда ему нужно только вернуть одно значение, а не последовательность? – Rawling