diff --git a/src/BenchmarkDotNet/Parameters/ParameterDefinition.cs b/src/BenchmarkDotNet/Parameters/ParameterDefinition.cs index 420fb61d2e..e91482bacd 100644 --- a/src/BenchmarkDotNet/Parameters/ParameterDefinition.cs +++ b/src/BenchmarkDotNet/Parameters/ParameterDefinition.cs @@ -1,4 +1,6 @@ -namespace BenchmarkDotNet.Parameters +using System; + +namespace BenchmarkDotNet.Parameters { public class ParameterDefinition { @@ -6,13 +8,15 @@ public class ParameterDefinition public bool IsStatic { get; } public object[] Values { get; } public bool IsArgument { get; } + public Type ParameterType { get; } - public ParameterDefinition(string name, bool isStatic, object[] values, bool isArgument) + public ParameterDefinition(string name, bool isStatic, object[] values, bool isArgument, Type parameterType) { Name = name; IsStatic = isStatic; Values = values; IsArgument = isArgument; + ParameterType = parameterType; } } } \ No newline at end of file diff --git a/src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs b/src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs index 6bdb10b35b..45044a955d 100644 --- a/src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs +++ b/src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs @@ -83,7 +83,7 @@ public SmartArgument(ParameterDefinition[] parameterDefinitions, object value, M public string ToSourceCode() { - string cast = $"({Value.GetType().GetCorrectCSharpTypeName()})"; // it's an object so we need to cast it to the right type + string cast = $"({parameterDefinitions[argumentIndex].ParameterType.GetCorrectCSharpTypeName()})"; // it's an object so we need to cast it to the right type string callPostfix = source is PropertyInfo ? string.Empty : "()"; diff --git a/src/BenchmarkDotNet/Running/BenchmarkConverter.cs b/src/BenchmarkDotNet/Running/BenchmarkConverter.cs index 2d957aed89..98f8125f68 100644 --- a/src/BenchmarkDotNet/Running/BenchmarkConverter.cs +++ b/src/BenchmarkDotNet/Running/BenchmarkConverter.cs @@ -174,7 +174,8 @@ IEnumerable GetDefinitions(Func((attribute, parameterType) => GetValidValues(attribute.Values, parameterType)); @@ -195,7 +196,7 @@ IEnumerable GetDefinitions(Func GetArgumentsDefinitions(MethodInfo benchmark, Type target) { var parameterDefinitions = benchmark.GetParameters() - .Select(parameter => new ParameterDefinition(parameter.Name, false, Array.Empty(), true)) + .Select(parameter => new ParameterDefinition(parameter.Name, false, Array.Empty(), true, parameter.ParameterType)) .ToArray(); if (parameterDefinitions.IsEmpty()) diff --git a/tests/BenchmarkDotNet.IntegrationTests/ArgumentsTests.cs b/tests/BenchmarkDotNet.IntegrationTests/ArgumentsTests.cs index 7167712157..20dfa24db6 100644 --- a/tests/BenchmarkDotNet.IntegrationTests/ArgumentsTests.cs +++ b/tests/BenchmarkDotNet.IntegrationTests/ArgumentsTests.cs @@ -171,6 +171,31 @@ public void AcceptingArray(int[] array) } } + [Theory, MemberData(nameof(GetToolchains))] + public void IEnumerableCanBeUsedAsArgument(IToolchain toolchain) => CanExecute(toolchain); + + public class WithIEnumerable + { + private static IEnumerable Iterator() { yield return 1; } + + public IEnumerable Sources() + { + yield return new object[] { "Empty", Enumerable.Empty() }; + yield return new object[] { "Range", Enumerable.Range(0, 10) }; + yield return new object[] { "List", new List() { 1, 2, 3 } }; + yield return new object[] { "int[]", new int[] { 1, 2, 3 } }; + yield return new object[] { "int[].Select", new int[] { 1, 2, 3 }.Select(i => i) }; + yield return new object[] { "int[].Select.Where", new int[] { 1, 2, 3 }.Select(i => i).Where(i => i % 2 == 0) }; + yield return new object[] { "Iterator", Iterator() }; + yield return new object[] { "Iterator.Select", Iterator().Select(i => i) }; + yield return new object[] { "Iterator.Select.Where", Iterator().Select(i => i).Where(i => i % 2 == 0) }; + } + + [Benchmark] + [ArgumentsSource(nameof(Sources))] + public void Any(string name, IEnumerable source) => source.Any(); + } + [Theory, MemberData(nameof(GetToolchains))] public void JaggedArrayCanBeUsedAsArgument(IToolchain toolchain) => CanExecute(toolchain); diff --git a/tests/BenchmarkDotNet.Tests/ParameterComparerTests.cs b/tests/BenchmarkDotNet.Tests/ParameterComparerTests.cs index a6dd1c4e97..4f4934955e 100644 --- a/tests/BenchmarkDotNet.Tests/ParameterComparerTests.cs +++ b/tests/BenchmarkDotNet.Tests/ParameterComparerTests.cs @@ -12,7 +12,7 @@ public void BasicComparisionTest() { var comparer = ParameterComparer.Instance; - var sharedDefinition = new ParameterDefinition("Testing", isStatic: false, values: Array.Empty(), isArgument: false); + var sharedDefinition = new ParameterDefinition("Testing", isStatic: false, values: Array.Empty(), isArgument: false, parameterType: null); var originalData = new[] { new ParameterInstances(new[] @@ -40,7 +40,7 @@ public void MultiParameterComparisionTest() { var comparer = ParameterComparer.Instance; - var sharedDefinition = new ParameterDefinition("Testing", isStatic: false, values: Array.Empty(), isArgument: false); + var sharedDefinition = new ParameterDefinition("Testing", isStatic: false, values: Array.Empty(), isArgument: false, parameterType: null); var originalData = new[] { new ParameterInstances(new[] @@ -94,7 +94,7 @@ public void AlphaNumericComparisionTest() { var comparer = ParameterComparer.Instance; - var sharedDefinition = new ParameterDefinition("Testing", isStatic: false, values: Array.Empty(), isArgument: false); + var sharedDefinition = new ParameterDefinition("Testing", isStatic: false, values: Array.Empty(), isArgument: false, parameterType: null); var originalData = new[] { new ParameterInstances(new[] diff --git a/tests/BenchmarkDotNet.Tests/ParameterInstanceTests.cs b/tests/BenchmarkDotNet.Tests/ParameterInstanceTests.cs index a9d31d59cb..20dc58bd48 100644 --- a/tests/BenchmarkDotNet.Tests/ParameterInstanceTests.cs +++ b/tests/BenchmarkDotNet.Tests/ParameterInstanceTests.cs @@ -7,7 +7,7 @@ namespace BenchmarkDotNet.Tests { public class ParameterInstanceTests { - private static readonly ParameterDefinition definition = new ParameterDefinition("Testing", isStatic: false, values: Array.Empty(), isArgument: false); + private static readonly ParameterDefinition definition = new ParameterDefinition("Testing", isStatic: false, values: Array.Empty(), isArgument: false, parameterType: null); [Theory] [InlineData(5)]