From cb40e8fbc87dc1726a710621964913d4fbf2febf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 16:53:59 +0000 Subject: [PATCH 1/2] Initial plan From a9d4e0774ca2077725e71c510315c40291e280c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 16:59:54 +0000 Subject: [PATCH 2/2] Add breaking change article for IDispatchEx to IReflect cast failure Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com> --- docs/core/compatibility/10.0.md | 1 + .../interop/10.0/idispatchex-ireflect-cast.md | 61 +++++++++++++++++++ docs/core/compatibility/toc.yml | 2 + 3 files changed, 64 insertions(+) create mode 100644 docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md diff --git a/docs/core/compatibility/10.0.md b/docs/core/compatibility/10.0.md index 787ec470e6c1a..0f8ae4c604350 100644 --- a/docs/core/compatibility/10.0.md +++ b/docs/core/compatibility/10.0.md @@ -99,6 +99,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af | Title | Type of change | |-------|-------------------| +| [Casting COM object that implements IDispatchEx to IReflect now fails](interop/10.0/idispatchex-ireflect-cast.md) | Behavioral change | | [Single-file apps no longer look for native libraries in executable directory](interop/10.0/native-library-search.md) | Behavioral change | | [Specifying DllImportSearchPath.AssemblyDirectory only searches the assembly directory](interop/10.0/search-assembly-directory.md) | Behavioral change | diff --git a/docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md b/docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md new file mode 100644 index 0000000000000..95b6e4d6ca9e0 --- /dev/null +++ b/docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md @@ -0,0 +1,61 @@ +--- +title: "Breaking change - Casting COM object that implements IDispatchEx to IReflect now fails" +description: "Learn about the breaking change in .NET 10 RC 1 where casting a COM object that implements IDispatchEx to IReflect now fails." +ms.date: 11/17/2025 +ai-usage: ai-assisted +--- + +# Casting COM object that implements IDispatchEx to IReflect now fails + +Since .NET 5, casting a COM object that implements `IDispatchEx` to `IReflect` has been possible. However, all members on that `IReflect` instance would throw . Starting in .NET 10 RC 1, this behavior changed so that the cast now fails. + +## Version introduced + +.NET 10 RC 1 + +## Previous behavior + +Previously, casting a COM object that implements `IDispatchEx` to `IReflect` would succeed. + +```csharp +using System.Reflection; +var file = Activator.CreateInstance(Type.GetTypeFromProgID("htmlfile")); +Console.WriteLine("IReflect is " + (file is IReflect ? "supported" : "NOT supported")); +// Prints "IReflect is supported" +``` + +## New behavior + +Starting in .NET 10, casting a COM object that implements `IDispatchEx` to `IReflect` now fails. + +```csharp +using System.Reflection; +var file = Activator.CreateInstance(Type.GetTypeFromProgID("htmlfile")); +Console.WriteLine("IReflect is " + (file is IReflect ? "supported" : "NOT supported")); +// Prints "IReflect is NOT supported" +``` + +## Type of breaking change + +This change is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +This was removed because all members on the resulting `IReflect` instance would be unusable. The exception that would result from accessing any of the members mentioned a type that was never included in .NET Core and was therefore confusing and unhelpful as to the underlying issue. Removal of the cast behavior was therefore deemed appropriate. + +## Recommended action + +The only viable question that could be asked in .NET 5+ with this cast was, "Does the type implement IDispatchEx?" In this case, the better way to ask that question is as follows: + +```csharp +var file = Activator.CreateInstance(Type.GetTypeFromProgID("htmlfile")); +Console.WriteLine("IDispatchEx is " + (file is IDispatchEx ? "supported" : "NOT supported")); + +[ComImport] +[Guid("A6EF9860-C720-11D0-9337-00A0C90DCAA9")] +interface IDispatchEx { } +``` + +## Affected APIs + +None. diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index fe5e041baa491..ddf6ae786d278 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -108,6 +108,8 @@ items: href: install-tool/3.0.0/vscode-dotnet-acquire-no-latest.md - name: Interop items: + - name: Casting COM object that implements IDispatchEx to IReflect now fails + href: interop/10.0/idispatchex-ireflect-cast.md - name: Single-file apps no longer look for native libraries in executable directory href: interop/10.0/native-library-search.md - name: Specifying DllImportSearchPath.AssemblyDirectory only searches the assembly directory