4

I know that in C# in general you can't create an instance of an abstract class or an interface. Can someone help me understand this code (it compile without any errors).

Shell32.Shell shObj = new Shell32.Shell();

Shell32.Shell is an interface from 'shell32.dll'

I tried the following, but it did NOT compile:

[CoClass(typeof(ShellClass))]
[Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")]
public interface OtherShell : Shell
{
}
OtherShell shObj = new OtherShell();

Update:

To make it work, I just needed to add the ComImport attribute and change the co-class (I can't choose Shell32.ShellClass).

Thanks guys!

user2864740
  • 60,010
  • 15
  • 145
  • 220
  • 3
    It's a COM object. An Interop Assembly is generated when the COM DLL is imported into the project. There is some other magic therein - the actual class is 'Shell32.ShellClass'. Using Code Navigation on the "new Shell" code moves to the ShellClass implementation, not the Shell interface, so there is further magic.. – user2864740 Oct 09 '18 at 15:57
  • 2
    What makes you think it is an interface? – Buh Buh Oct 09 '18 at 15:59
  • @BuhBuh Viewing the interop assembly: "[Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")] [CoClass(typeof (ShellClass))] [ComImport] public *interface* Shell .." (ShellClass extends Shell). – user2864740 Oct 09 '18 at 15:59
  • 3
    Short answer: You are correct that interfaces cannot be instantiated. What you've stumbled upon is some piece of obscure syntactic sugar that facilitates instantiation of COM classes. – Theodoros Chatzigiannakis Oct 09 '18 at 16:02
  • 1
    No need to mark questions solved - the answers do that. You can always answer your own questions. – user2864740 Oct 09 '18 at 16:30

2 Answers2

2

In addition to all the other information, here is the how it results in compiled code. The usage of the interface is merely a code nicety.

IL_000c: newobj       instance void [Interop.Shell32]Shell32.ShellClass::.ctor()

That is, it is a compile-time transformation from the interface "to" the class, based on the [CoClass] attribute.

Per, https://stackoverflow.com/a/1094140/2864740, which shows a minimal example case:

[In addition to CoClassAttribute, you] need both the ComImportAttribute and the GuidAttribute for it to work.

user2864740
  • 60,010
  • 15
  • 145
  • 220
1

If you right click in Visual Studio on Shell32.Shell and go to definition you'll get the following definition of the interface:

using System.Runtime.InteropServices;

namespace Shell32
{
    [CoClass(typeof(ShellClass))]
    [Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")]
    public interface Shell : IShellDispatch6
    {
    }
}

Do the same on the ShellClass and you'll get the concrete class that's being created in your code:

Shell32.Shell shObj = new Shell32.Shell();
Tom John
  • 783
  • 5
  • 14
  • I wonder what is responsible for "creating" the object (for the right impl.) to honor the CoClass attribute..? That is, how does C#/specify know that this interface is special, or is the attribute itself sufficient (at what 'level' does the magic occur)? Is there special MSIL generated (and/or how does it differ from a normal ctor call); that is, is it run-time or compile-time magic to select the ShellClass? Where might this be documented? – user2864740 Oct 09 '18 at 16:02
  • CoClassAttribute is discussed here https://stackoverflow.com/questions/6960910/what-does-the-c-sharp-coclass-attribute-do – Tom John Oct 09 '18 at 16:07
  • That also only gives a high-level explanation, but not the details :( If we've decided that .NET *can't* instantiate interfaces, then there has to be some 'special mechanism' by which the looks-like-interface-instantiation is "converted" to the actual object creation. – user2864740 Oct 09 '18 at 16:08
  • @Adrian Answers there still say 'what to make it work', without saying *how* it works.. :} – user2864740 Oct 09 '18 at 16:10
  • Get hold of the source code (it's all available) and dig through https://referencesource.microsoft.com/#mscorlib/system/runtime/interopservices/attributes.cs,7288373bd0dc8648 – Tom John Oct 09 '18 at 16:12