我只是想知道我是不是漏掉了一些语法糖或微优化...如果我调用一个方法需要一个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,所以我决定测试一下这四个想法。这四个想法是
new[] { x }
)这些可以从下面的代码中更好的理解。
[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的一部分。
数组是一个数组的具体实现。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);
}
据我所知不是这样的,不是这样的。相反,你应该考虑创建一个接受单个参数的方法,而另一个方法则接受一个 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)
}