Skip to content

GeneratedComInterfaceAttribute can cause CS0108 error with two derived COM interfaces declaring methods with same name and signature #101240

Closed
@smourier

Description

@smourier

Description

When using .NET8's GeneratedComInterfaceAttribute, we cannot define a derived interface with a method that has the same name and signature (parameters) as a method (unrelated in vtable) on a base interface, it raises CS0108 "'member1' hides inherited member 'member2'. Use the new keyword if hiding was intended."

Reproduction Steps

Consider this simple .NET 8 project:

<Project Sdk="Microsoft.NET.Sdk">

	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net8.0</TargetFramework>
		<Nullable>enable</Nullable>
		<PublishAot>true</PublishAot>
		<InvariantGlobalization>true</InvariantGlobalization>
		<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
	</PropertyGroup>

</Project>

Add these interfaces definitions:

    [GeneratedComInterface, Guid("e4817011-64d7-4626-a2ed-ac0cf6ad76e7")]
    public partial interface IFace1
    {
        void Blah(nint p);
    }

    [GeneratedComInterface, Guid("5fdae1bd-24db-43cd-88e5-3825fac0f827")]
    public partial interface IFace2 : IFace1
    {
        void Blah2(nint p);

        void Blah(nint p); // this is where the problem lies (same name and same parameters as in IFace1)
    }

Expected behavior

I think it should just compile fine.

Actual behavior

Building creates these errors (all related):

1> c:\temp\ConsoleApp6.Program.IFace2.cs(31,45,31,49): warning CS0473: Explicit interface implementation 'InterfaceImplementation.Program.IFace2.Blah(nint)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead.
1> c:\temp\ConsoleApp6.Program.IFace2.cs(46,45,46,49): warning CS0473: Explicit interface implementation 'InterfaceImplementation.Program.IFace2.Blah(nint)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead.
1> c:\temp\ConsoleApp6.Program.IFace2.cs(12,31,12,54): error CS8646: 'Program.IFace2.Blah(nint)' is explicitly implemented more than once.
1> c:\temp\ConsoleApp6.Program.IFace2.cs(46,45,46,49): error CS0111: Type 'InterfaceImplementation' already defines a member called 'global::ConsoleApp6.Program.IFace2.Blah' with the same parameter types
1>E:\smo\work\ConsoleApp33\ConsoleApp6\Program.cs(51,18,51,22): warning CS0108: 'Program.IFace2.Blah(nint)' hides inherited member 'Program.IFace1.Blah(nint)'. Use the new keyword if hiding was intended.
1> c:\temp\ConsoleApp6.Program.IFace2.cs(144,22,144,26): error CS0111: Type 'Program.IFace2' already defines a member called 'Blah' with the same parameter types
1>Done building project "ConsoleApp6.csproj" -- FAILED.

Regression?

I don't think so since GeneratedComInterfaceAttribute is pretty new.

Known Workarounds

We can just rename IFace2's Blah with something else that doesn't conflict as COM names are not technically important but this raises lots of other issues, especially with .NET where names are.

Note that if if define IFace2's like this:

    [GeneratedComInterface, Guid("5fdae1bd-24db-43cd-88e5-3825fac0f827")]
    public partial interface IFace2 : IFace1
    {
        void Blah2(nint p);

        new void Blah(nint p);
    }

There are other errors, but the most interesting is this:

1>c:\temp\ConsoleApp6.Program.IFace2.cs(31,49,31,53): error CS0106: The modifier 'new' is not valid for this item

which is kinda strange, this typically works with .NET default marshaling.

Configuration

.NET 8.0.4 (tested on x64 but I don't think it's relevant here).

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

Status

No status

Relationships

None yet

Development

No branches or pull requests

Issue actions