From e1ce5fbdbedb63c0470f1f6d374c7b0ed39e620e Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Mon, 11 Sep 2023 14:04:24 -0700 Subject: [PATCH 1/2] Allow As to return null for reference types --- .../src/Variant/Variant.cs | 3 ++- .../tests/Variant/VariantUsage.cs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs b/sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs index ec3264b5edd2..b9954f26af25 100644 --- a/sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs +++ b/sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs @@ -1296,11 +1296,12 @@ private readonly bool TryGetObjectSlow(out T value) { // Single return has a significant performance benefit. - bool result = false; + bool result; if (_object is null) { value = default!; + result = true; } else if (typeof(T) == typeof(char[])) { diff --git a/sdk/core/Azure.Core.Experimental/tests/Variant/VariantUsage.cs b/sdk/core/Azure.Core.Experimental/tests/Variant/VariantUsage.cs index 3c115b0ae7b6..c145bb99e60d 100644 --- a/sdk/core/Azure.Core.Experimental/tests/Variant/VariantUsage.cs +++ b/sdk/core/Azure.Core.Experimental/tests/Variant/VariantUsage.cs @@ -91,6 +91,22 @@ public void VariantAssignmentHasReferenceSemantics() Assert.AreEqual("3", b.As>()[0]); } + [Test] + public void ReferenceTypesCanBeNull() + { + string s = null; + Variant stringVariant = new(s); + + Assert.AreEqual(Variant.Null, stringVariant); + Assert.IsNull(stringVariant.As()); + + List list = null; + Variant listVariant = new(list); + + Assert.AreEqual(Variant.Null, listVariant); + Assert.IsNull(listVariant.As()); + } + #region Helpers public static IEnumerable VariantValues() { From 20ca645978dce7f19707a619c5c63717c6b08b42 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Mon, 11 Sep 2023 14:27:26 -0700 Subject: [PATCH 2/2] Improve cast exception message --- .../src/Variant/Variant.cs | 16 ++++++++++++--- .../tests/Variant/VariantUsage.cs | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs b/sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs index b9954f26af25..12cb8bd9efd0 100644 --- a/sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs +++ b/sdk/core/Azure.Core.Experimental/src/Variant/Variant.cs @@ -77,7 +77,17 @@ public readonly Type? Type } [DoesNotReturn] - private static void ThrowInvalidCast() => throw new InvalidCastException(); + private static void ThrowInvalidCast(Type? source, Type target) + { + if (source is null) + { + throw new InvalidCastException($"Unable to cast null Variant to type '{target}'."); + } + else + { + throw new InvalidCastException($"Unable to cast Variant of type '{source}' to type '{target}'."); + } + } [DoesNotReturn] private static void ThrowArgumentNull(string paramName) => throw new ArgumentNullException(paramName); @@ -1381,9 +1391,9 @@ private readonly bool TryGetObjectSlow(out T value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly T As() { - if (!TryGetValue(out T value)) + if (!TryGetValue(out T value)) { - ThrowInvalidCast(); + ThrowInvalidCast(Type, typeof(T)); } return value; diff --git a/sdk/core/Azure.Core.Experimental/tests/Variant/VariantUsage.cs b/sdk/core/Azure.Core.Experimental/tests/Variant/VariantUsage.cs index c145bb99e60d..23c8b43815fb 100644 --- a/sdk/core/Azure.Core.Experimental/tests/Variant/VariantUsage.cs +++ b/sdk/core/Azure.Core.Experimental/tests/Variant/VariantUsage.cs @@ -107,6 +107,26 @@ public void ReferenceTypesCanBeNull() Assert.IsNull(listVariant.As()); } + [Test] + public void NonNullableValueTypesCannotBeNull() + { + int? i = null; + Variant intVariant = new(i); + + Assert.AreEqual(Variant.Null, intVariant); + Assert.Throws(() => intVariant.As()); + } + + [Test] + public void NullableValueTypesCanBeNull() + { + int? i = null; + Variant intVariant = new(i); + + Assert.AreEqual(Variant.Null, intVariant); + Assert.IsNull(intVariant.As()); + } + #region Helpers public static IEnumerable VariantValues() {