Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 17, 2025

Summary

Documents the .NET 10 behavioral change where casting COM objects implementing IDispatchEx to IReflect now fails instead of succeeding with unusable members.

Changes:

  • Created breaking change article at docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md
  • Updated TOC and index files to include the new article

Previous behavior (.NET 5-9):

var file = Activator.CreateInstance(Type.GetTypeFromProgID("htmlfile"));
Console.WriteLine(file is IReflect ? "supported" : "NOT supported");
// Prints "supported" (but all IReflect members threw TypeLoadException)

New behavior (.NET 10):

var file = Activator.CreateInstance(Type.GetTypeFromProgID("htmlfile"));
Console.WriteLine(file is IReflect ? "supported" : "NOT supported");
// Prints "NOT supported"

Recommended migration:

Console.WriteLine(file is IDispatchEx ? "supported" : "NOT supported");

[ComImport]
[Guid("A6EF9860-C720-11D0-9337-00A0C90DCAA9")]
interface IDispatchEx { }

Fixes #46690

Original prompt

This section details on the original issue you should resolve

<issue_title>[Breaking change]: Casting COM object that implements IDispatchEx to IReflect now fails</issue_title>
<issue_description>### Description

Since .NET 5, the ability to cast a COM object that implements IDispatchEx to IReflect has been possible. However, all members on that IReflect instance would throw TypeLoadException. In .NET 10 this behavior changed so that the cast will fail.

Version

.NET 10 RC 1

Previous behavior

Casting a COM object that implements IDispatchEx to IReflect would succeed.

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

Casting a COM object that implements IDispatchEx to IReflect will now fail.

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

  • Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
  • Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
  • Behavioral change: Existing binaries might behave differently at run time.

Reason for change

This was removed since all members on the resulting IReflect instance would be unusable. The TypeLoadException 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:

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 { }

Feature area

Interop

Affected APIs

This doesn't impact any specific .NET API.</issue_description>

Comments on the Issue (you are @copilot in this section)

@AaronRobinsonMSFT /cc @davidwrighton @jkotas @ClearScriptLib @AaronRobinsonMSFT /cc @dotnet/interop-contrib @AaronRobinsonMSFT > Why will `file is IReflect` throw; shouldn't it return `false`?

Updated.</comment_new>


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.


Internal previews

📄 File 🔗 Preview link
docs/core/compatibility/10.0.md docs/core/compatibility/10.0
docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast
docs/core/compatibility/toc.yml docs/core/compatibility/toc

Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix casting COM object to IReflect in .NET 10 Add breaking change documentation for IDispatchEx to IReflect cast failure in .NET 10 Nov 17, 2025
Copilot AI requested a review from gewarren November 17, 2025 17:01
Copilot finished work on behalf of gewarren November 17, 2025 17:01
@gewarren gewarren marked this pull request as ready for review November 17, 2025 17:20
@gewarren gewarren requested a review from a team as a code owner November 17, 2025 17:20
Copilot AI review requested due to automatic review settings November 17, 2025 17:20
@gewarren gewarren marked this pull request as draft November 17, 2025 17:20
Copilot finished reviewing on behalf of gewarren November 17, 2025 17:22
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR documents a .NET 10 breaking change where casting COM objects implementing IDispatchEx to IReflect now fails instead of succeeding with unusable members.

  • Adds comprehensive breaking change documentation explaining the behavioral change, reason, and recommended migration path
  • Updates TOC and index files to include the new article in the interop section
  • Provides clear before/after code examples demonstrating the behavior change

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
docs/core/compatibility/interop/10.0/idispatchex-ireflect-cast.md New breaking change article documenting the IDispatchEx to IReflect cast failure in .NET 10 with code examples and migration guidance
docs/core/compatibility/toc.yml Adds TOC entry for the new breaking change article in the Interop section
docs/core/compatibility/10.0.md Adds index entry for the new breaking change in the Interop category

@@ -0,0 +1,61 @@
---
title: "Breaking change - Casting COM object that implements IDispatchEx to IReflect now fails"
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type names like IDispatchEx and IReflect should be wrapped in backticks for code formatting according to .NET documentation guidelines. Change the title to: "Breaking change: Casting COM object that implements IDispatchEx to IReflect now fails".

Copilot generated this review using guidance from repository custom instructions.
@@ -0,0 +1,61 @@
---
title: "Breaking change - Casting COM object that implements IDispatchEx to IReflect now fails"
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to markdown writing guidelines, use a colon instead of a hyphen in the title. Change "Breaking change -" to "Breaking change:".

Copilot generated this review using guidance from repository custom instructions.
@@ -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."
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type names like IDispatchEx and IReflect should be wrapped in backticks for code formatting according to .NET documentation guidelines. Update the description to include backticks around these type names.

Copilot generated this review using guidance from repository custom instructions.

```csharp
var file = Activator.CreateInstance(Type.GetTypeFromProgID("htmlfile"));
Console.WriteLine("IDispatchEx is " + (file is IDispatchEx ? "supported" : "NOT supported"));
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove trailing whitespace at the end of the line.

Suggested change
Console.WriteLine("IDispatchEx is " + (file is IDispatchEx ? "supported" : "NOT supported"));
Console.WriteLine("IDispatchEx is " + (file is IDispatchEx ? "supported" : "NOT supported"));

Copilot uses AI. Check for mistakes.

## 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:
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use second person ("you") instead of passive voice. Change "In this case, the better way to ask that question is as follows:" to "In this case, ask that question as follows:" to follow the active voice with second person requirements.

Copilot generated this review using guidance from repository custom instructions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Breaking change]: Casting COM object that implements IDispatchEx to IReflect now fails

2 participants