有没有办法调用一个需要IEnumerable<T>单值的C#方法?...与基准[重复]。

问题描述 投票:1回答:1

我只是想知道我是不是漏掉了一些语法糖或微优化...如果我调用一个方法需要一个IEnumerable的值,但我只有一个值,那么我就把这个单值放在一个数组里.例如:

var x = 1.23;
SquareAllTheNumbers(new[] { x });


private void SquareAllTheNumbers(IEnumerable<double> values)
{
    foreach (var value in values)
    {
        Console.WriteLine(Math.Sqrt(value));
    }
}

这就需要一个数组,即使不需要。这样看来,我应该可以写出这样的内容。

var x = 1.23;
SquareAllTheNumbers(yield x);

有没有办法在不建立数组的情况下调用函数?

(编辑)谢谢大家的快速回复。所以,我了解到的是,有四种解决方法,如下文指出的,在过去相同的问题(传递一个单项作为IEnumerable<T>). 我当然喜欢额外的产额方法,而且这样也不需要生成一个新的数组,但是这样更好吗?好吧,我一直想多了解一下Benchmark.NET,所以我决定测试一下这四个想法。这四个想法是

  1. 生成一个数组 (new[] { x } )
  2. 屈服法
  3. Enumerable.Repeat
  4. 参数 double[]

这些可以从下面的代码中更好的理解。

        [Benchmark(Description = "Array Approach")]
        public double ArrayApproach()
        {
            var x = 1.23;
            return SumOfSquaredNumbers(new[] { x });
        }

        [Benchmark(Description = "Yield Method Approach")]
        public double YieldMethodApproach()
        {
            return SumOfSquaredNumbers(Yield(x));
        }

        [Benchmark(Description = "Enumerable Repeat Approach")]
        public double RepeatMethodApproach()
        {
            return SumOfSquaredNumbers(Enumerable.Repeat(x, 1));
        }
        [Benchmark(Description = "Params Approach")]
        public double ParamsApproach()
        {
            return SumOfSquaredNumbers(x);
        }

        private double SumOfSquaredNumbers(IEnumerable<double> values)
        {
            var result = 0.0;
            foreach (var value in values)
            {
                result = value * value;
            }

            return result;
        }
        private double SumOfSquaredNumbers(params double[] values)
        {
            var result = 0.0;
            foreach (var value in values)
            {
                result = value * value;
            }

            return result;
        }

        public IEnumerable<T> Yield<T>(T item)
        {
            yield return item;
        }

这是基准测试的结果。

|                       Method |      Mean |      Error |    StdDev |  Gen 0 | Allocated |
|----------------------------- |----------:|-----------:|----------:|-------:|----------:|
|             'Array Approach' |  6.970 ns | 10.7471 ns | 0.5891 ns | 0.0076 |      32 B |
|      'Yield Method Approach' | 30.256 ns | 21.7358 ns | 1.1914 ns | 0.0114 |      48 B |
| 'Enumerable Repeat Approach' | 30.058 ns | 32.9930 ns | 1.8085 ns | 0.0095 |      40 B |
|            'Params Approach' |  5.330 ns |  0.6169 ns | 0.0338 ns | 0.0077 |      32 B |

所以,看起来最好的方法是直接新建一个数组。第四种方案(使用 params double[])执行得很好,但这有点超出了问题的范围,因为我的意思是该方法是 "一成不变的"--例如,第三方DLL的一部分。

c# collections ienumerable
1个回答
1
投票

数组是一个数组的具体实现。IEnumerable所以我觉得创建一个传递值的函数没有什么问题。

如果你需要的是语法上的糖分,你可以用一个重载来实现 params 参数,这意味着编译器会帮你创建一个数组。

private static void SquareAllTheNumbers(params double[] values) {
    foreach (var value in values) {
        Console.WriteLine(Math.Sqrt(value));
    }
}

static void Main(string[] args) {
    SquareAllTheNumbers(2);
    SquareAllTheNumbers(1,2,3);
}

0
投票

据我所知不是这样的,不是这样的。相反,你应该考虑创建一个接受单个参数的方法,而另一个方法则接受一个 IEnumerable 同一参数的。E.G

// May need to be renamed, as it implies this method returns value^2 but actually returns value^(1/2)
private double SquareNumber(double value)
{
    return Math.Sqrt(value);
}

private IEnumerable<double> SquareAllTheNumbers(IEnumerable<double> values)
{
    foreach (var value in values)
       yield return Math.Sqrt(value)
}
© www.soinside.com 2019 - 2024. All rights reserved.