diff --git a/src/NSubstitute/Core/DefaultForType.cs b/src/NSubstitute/Core/DefaultForType.cs index f1fde93a..d20909fc 100644 --- a/src/NSubstitute/Core/DefaultForType.cs +++ b/src/NSubstitute/Core/DefaultForType.cs @@ -46,6 +46,15 @@ private object DefaultInstanceOfValueType(Type returnType) return BoxedDouble; } - return Activator.CreateInstance(returnType)!; + // Need to have a special case for Nullable to return null. + if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + return null!; + } +#if NET5_0_OR_GREATER + return System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(returnType); +#else + return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(returnType); +#endif } } \ No newline at end of file diff --git a/src/NSubstitute/Routing/AutoValues/AutoObservableProvider.cs b/src/NSubstitute/Routing/AutoValues/AutoObservableProvider.cs index 713a5bde..8d768534 100644 --- a/src/NSubstitute/Routing/AutoValues/AutoObservableProvider.cs +++ b/src/NSubstitute/Routing/AutoValues/AutoObservableProvider.cs @@ -21,6 +21,7 @@ public bool CanProvideValueFor(Type type) => private static object? GetDefault(Type type) { - return type.GetTypeInfo().IsValueType ? Activator.CreateInstance(type) : null; + var defaultForType = new DefaultForType(); + return defaultForType.GetDefaultFor(type); } } diff --git a/src/NSubstitute/Routing/AutoValues/AutoTaskProvider.cs b/src/NSubstitute/Routing/AutoValues/AutoTaskProvider.cs index 13d365f3..a7be528b 100644 --- a/src/NSubstitute/Routing/AutoValues/AutoTaskProvider.cs +++ b/src/NSubstitute/Routing/AutoValues/AutoTaskProvider.cs @@ -1,3 +1,4 @@ +using NSubstitute.Core; using System.Reflection; namespace NSubstitute.Routing.AutoValues; @@ -32,6 +33,7 @@ public object GetValue(Type type) private static object? GetDefault(Type type) { - return type.GetTypeInfo().IsValueType ? Activator.CreateInstance(type) : null; + var defaultForType = new DefaultForType(); + return defaultForType.GetDefaultFor(type); } } diff --git a/tests/NSubstitute.Acceptance.Specs/ArgumentMatching.cs b/tests/NSubstitute.Acceptance.Specs/ArgumentMatching.cs index b43ef848..b0b2a16b 100644 --- a/tests/NSubstitute.Acceptance.Specs/ArgumentMatching.cs +++ b/tests/NSubstitute.Acceptance.Specs/ArgumentMatching.cs @@ -866,6 +866,27 @@ public void Does_support_out_method_with_base_override() Assert.That(outArg, Is.EqualTo(4)); } + [Test] + public void Any_on_struct_with_default_constructor_should_work() + { + var something = Substitute.For(); + Assert.DoesNotThrow(() => something.MethodWithStruct(Arg.Any())); + } + + public struct StructWithDefaultConstructor + { + public int Value { get; set; } + public StructWithDefaultConstructor() + { + Value = 42; + } + } + + public interface IWithStructWithDefaultConstructor + { + void MethodWithStruct(StructWithDefaultConstructor arg); + } + [SetUp] public void SetUp() {