首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >扩展方法Average() C#

扩展方法Average() C#
EN

Stack Overflow用户
提问于 2020-11-22 20:39:36
回答 4查看 232关注 0票数 0

首先,你们都需要知道,我不想在C#中使用LINQ库。

现在我想写一个扩展方法,返回不同列表的平均值。这是列表

代码语言:javascript
复制
integers = new List<int> { 5, 76, 3, 93, 143, 5, 11, 67, 5 };
doubles = new List<double> { 1.23, 68.256, 44.55, 96.127, 393.4567, 2.45, 4.1 };
persons = new List<Person>
{
   new Person {Firstname = "John", Lastname = "last", Age = 66, Sallary = 1513},
   new Person {Firstname = "Donald", Lastname = "last", Age = 77, Sallary = 3100}
};

这是我已经得到的:

代码语言:javascript
复制
  public static double Average(this IEnumerable<int> source)
    {
        IList<int> list = source as IList<int>;
        if (source == null) throw new ArgumentNullException("Err");
        long sum = 0;
        for (int i = 0; i < list.Count; i++)
        {
            sum += list[i];
        }
        return sum / list.Count;
    }

我只能计算我的整数列表的平均值。我还想计算双重列表的平均值和我的人员列表的平均工资。

这就是我将如何调用计算人员列表平均工资的函数

代码语言:javascript
复制
persons.Average(x => x.Sallary).ShowSingle("persons.Average(x => x.Sallary)");
EN

回答 4

Stack Overflow用户

发布于 2020-11-22 21:03:04

首先,您的Average方法返回了错误的整数列表结果,因为您使用了整数除法(它返回45而不是45.3333)。

要使它与double一起工作,您需要创建一个使用IEnumerable<double>等的重载。

代码语言:javascript
复制
public static double Average(this IEnumerable<double> source)
{
    IList<double> list = source as IList<double>;

    if (source == null || source.Count == 0)
        throw new ArgumentNullException("Err");

    double sum = 0;

    for (int i = 0; i < list.Count; i++)
    {
        sum += list[i];
    }

    return sum / list.Count;
}

您可以通过使用foreach来简化该方法

代码语言:javascript
复制
public static double Average(this IEnumerable<double> source)
{
    if (source == null)
        throw new ArgumentNullException("Err");

    double sum = 0;
    int count = 0;

    foreach (double entry in source)
    {
        sum += entry;
        count+=1;
    }

    if (count == 0) return 0;

    return sum / count;
}
票数 2
EN

Stack Overflow用户

发布于 2020-11-22 22:40:25

就像我在评论中写的那样,您可以使用Linq存储库中的实现。我刚刚改变了他们对0个项目的处理方式。

代码语言:javascript
复制
    public static double Average(this IEnumerable<int> source)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        long sum = 0;
        long count = 0;
        checked
        {
            foreach (int v in source)
            {
                sum += v;
                count++;
            }
        }
        if (count == 0)
        {
            return 0;
        }
        return (double)sum / count;
    }

    public static double Average<T>(this IEnumerable<T> source)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }
        if(typeof(T) != typeof(int)
            && typeof(T) != typeof(double)
            && typeof(T) != typeof(float)
            && typeof(T) != typeof(decimal)
            && typeof(T) != typeof(long))
        {
            throw new InvalidOperationException($"Wrong type specified: {typeof(T)}");
        }

        double sum = 0;
        long count = 0;
        checked
        {
            foreach (T v in source)
            {
                sum += Convert.ToDouble(v);
                count++;
            }
        }
        if (count == 0)
        {
            return 0;
        }
        return (double)sum / count;
    }

可以通过here打开一个工作示例

当然,原始的Linq代码可以在here中找到

票数 0
EN

Stack Overflow用户

发布于 2020-11-22 23:28:47

我只能计算我的整数列表的平均值。我还想计算双重列表的平均值和我的人员列表的平均工资。

正如一些用户在评论中提到的,最好将其提取到单独的例程中。就像克劳斯上面提到的,Compile-time checking is always better than run-time checking (better performance, better and earlier diagnostics)。我同意,但正如我在另一个答案中提到的,这是否意味着它是程序员的糟糕设计,还是作者的糟糕的面向对象设计?

下面是一个使用泛型的小示例(<T>),一个例程执行intdouble列表,另一个例程(用于Person)提取到它自己的例程中。第一个Average例程使用Convert.ChangeType的帮助返回其值等于指定对象的指定类型。

代码语言:javascript
复制
public static class Extensions
    {
        public static T Average<T>(this IEnumerable<T> source)
        {
            double dblSum = 0;
            int intSum = 0;

            if (source == null)
                throw new ArgumentNullException("Err");
            if (typeof(T) == typeof(int) && source is List<int> intList && intList.Count > 0)
            {
                for (int i = 0; i < intList.Count; i++)
                {
                    intSum += intList[i];
                }
                return (T)Convert.ChangeType((intSum / intList.Count), typeof(T));
            }
            else if (typeof(T) == typeof(double) && source is List<double> dblList && dblList.Count > 0)
            {
                for (int i = 0; i < dblList.Count; i++)
                {
                    dblSum += dblList[i];
                }
                return (T)Convert.ChangeType((dblSum / dblList.Count), typeof(T));
            }
            else
            {
                return default;
            }
        }

        public static int Average(this IEnumerable<Person> people)
        {
            int intSum = 0;
            if (people != null && people is List<Person> perList && perList.Count > 0)
            {
                for (int i = 0; i < perList.Count; i++)
                {
                    intSum += perList[i].Sallary;
                }
                return intSum / perList.Count;
            }
            else
            {
                return default;
                // throw new ArgumentNullException("Err");
            }

        }
    }

请注意:我不确定Sallary的类型,因为你的帖子中没有提供这一点。您可能需要稍微更改Average例程(Person)以适应您的Sallary类型。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64954225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档