首页 > 解决方案 > C# - 接受任何类型的 IEnumerable 作为参数

问题描述

我有这个构造函数,它应该接受任何类型的任何 IEnumerable,并尝试将值转换为所需的类型

public ChartData(IEnumerable<dynamic> labels, IEnumerable<dynamic> values)
            {
                this.values = values.Select(x=>(float)Convert.ToString(x));
                this.labels = labels.Select(x=>(string)Convert.ToString(x));
            }

当我调用这个构造函数时,我可以传递字符串类型的 ienumerables,但不能传递 int 或 float 我如何创建一个可以接受任何类型的 ienumerables 而不会产生大量重载的构造函数?

标签: c#dynamiccasting

解决方案


如果您接受任何类型,也包括IEnumerable<User>and IEnumerable<Car>,您希望如何将它们转换为浮点数和字符串?最好有一个封装浮点数和字符串值的对象,为此使用接口。例如,有一个这样的界面:

public interface IChartItem
{
    float Value { get; set; }
    string Label { get; set; }
}

一个示例类:

public class Foo : IChartItem
{
    public int MyProperty { get; set; }
    public string Name { get; set; }
    
    public float Value => (float)MyProperty;
    public string Label => Name;
}

现在您的函数可以是具有约束的通用函数:

public void ChartData<T>(IEnumerable<T> items)
    where T : IChartItem
{
    this.values = items.Select(x => x.Value);
    this.labels = items.Select(x => x.Label);
}

替代选项

您还可以传入您的对象以及几个Func参数来获取值和标签。例如:

public void ChartData<T>(IEnumerable<T> items, 
    Func<T, float> valueSelector, 
    Func<T, string> labelSelector)
{
    this.values = items.Select(x => valueSelector(x));
    this.labels = items.Select(x => labelSelector(x));
}

并像这样使用它:

ChartData(foos, f => (float)f.MyProperty, f => f.Name);

推荐阅读