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/3] 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/3] 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 From 6650673ae4e3bcbffdf1307b6e1fa79c9fea6f59 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:42:20 -0800 Subject: [PATCH 3/3] human edits --- docs/core/compatibility/10.0.md | 2 +- .../interop/10.0/idispatchex-ireflect-cast.md | 24 +++++++++---------- docs/core/compatibility/toc.yml | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/core/compatibility/10.0.md b/docs/core/compatibility/10.0.md index 0f8ae4c604350..49dc4efbdc5d7 100644 --- a/docs/core/compatibility/10.0.md +++ b/docs/core/compatibility/10.0.md @@ -99,7 +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 | +| [Casting IDispatchEx COM object to IReflect 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 index 95b6e4d6ca9e0..4d6c69fe68764 100644 --- a/docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md +++ b/docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md @@ -1,38 +1,38 @@ --- -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." +title: "Breaking change - Casting IDispatchEx COM object to IReflect fails" +description: "Learn about the breaking change in .NET 10 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 +# Casting COM object that implements IDispatchEx to IReflect 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. +Since .NET 5, it was possible to cast a COM object that implements [IDispatchEx](/previous-versions/windows/internet-explorer/ie-developer/windows-scripting/reference/idispatchex-interface) to . However, all members on that `IReflect` instance threw . Starting in .NET 10, this behavior changed and the cast now fails. ## Version introduced -.NET 10 RC 1 +.NET 10 ## Previous behavior -Previously, casting a COM object that implements `IDispatchEx` to `IReflect` would succeed. +Previously, casting a COM object that implements `IDispatchEx` to `IReflect` succeeded. ```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" +// Printed "IReflect is supported". ``` ## New behavior -Starting in .NET 10, casting a COM object that implements `IDispatchEx` to `IReflect` now fails. +Starting in .NET 10, casting a COM object that implements `IDispatchEx` to `IReflect` 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" +// Prints "IReflect is NOT supported". ``` ## Type of breaking change @@ -41,15 +41,15 @@ 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. +This capability was removed because all members on the resulting `IReflect` instance were unusable. Also, the exception that resulted from accessing any of the members mentioned a type that was never included in .NET and was therefore confusing and unhelpful as to the underlying issue. ## 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: +The only viable question that could be asked in .NET 5+ with this cast was, "Does the type implement IDispatchEx?" In this case, a better way to ask that question is: ```csharp var file = Activator.CreateInstance(Type.GetTypeFromProgID("htmlfile")); -Console.WriteLine("IDispatchEx is " + (file is IDispatchEx ? "supported" : "NOT supported")); +Console.WriteLine("IDispatchEx is " + (file is IDispatchEx ? "supported" : "NOT supported")); [ComImport] [Guid("A6EF9860-C720-11D0-9337-00A0C90DCAA9")] diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index ddf6ae786d278..6cd7b620d05e7 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -108,7 +108,7 @@ 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 + - name: Casting IDispatchEx COM object to IReflect 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