Поделиться через


Calling new on an interface

Interesting thing: technically there is a way to call new on an interface to create an object. How? Using a feature in the C# compiler for COM-interop support:

 using System.Runtime.InteropServices;

class Program
{
    static void Main(string[] args)
    {
        IFoo foo = new IFoo();
    }
}

class Foo : IFoo
{
}

[ComImport]
[Guid("DC1CB768-0BE5-4200-8D0A-C844BFBE3DE7")]
[CoClass(typeof(Foo))]
interface IFoo
{
}

Here you specify that Foo is a CoClass for the interface IFoo using the three attributes CoClass, ComImport and Guid. It does not matter that no real COM objects are involved, C# compiler is fine with that. What it does, it replaces the call to the IFoo() "constructor" to the equivalent constructor on the co-class Foo.

Interestingly enough, Foo doesn't have to even implement IFoo - the program will compile just fine and it will create an instance of type Foo at runtime, but it will fail when we try to put an object of type Foo into a local variable of type IFoo.

It's yet another way to instantiate a type without mentioning it in source code. As such, it can potentially be a way to achieve what factory methods do - instead of mentioning the concrete type in instantiations all over your code, you can just have a centralized place where you say what type to instantiate. With this you can easily substitute the concrete type via the CoClass attribute.

However, this is not as powerful as factory methods (you have to recompile your app to change concrete class and you can't have multiple concrete types at the same time).

I wouldn't encourage using this stuff anyway because this will probably confuse readers who read your source. But despite of anything, this *is * an interesting technique.

Comments

  • Anonymous
    August 15, 2009
    The comment has been removed

  • Anonymous
    August 15, 2009
    "However, this is not as powerful as factory methods (you have to recompile your app to change concrete class and you can't have multiple concrete types at the same time)." In this case, Unity is probably the solution.

  • Anonymous
    August 15, 2009
    The comment has been removed

  • Anonymous
    August 15, 2009
    Matthieu: wow, I didn't even know about http://www.codeplex.com/unity. It all looks like MEF to me :) Need to check it out.

  • Anonymous
    August 16, 2009
    Kirill, when would anyone EVER need to use this to solve OO problems more efficiently?

  • Anonymous
    August 16, 2009
    Awesome :) When I knew that you don't have to implement IEnumerable in your collection to use it in foreach statement, I had about the same feeling :)

  • Anonymous
    August 16, 2009
    Matt: I have NO IDEA. But I personally feel it's important to know all the options. It's like having a rich toolset - you never know when you might need a tool. Eugene: we understand each other :)

  • Anonymous
    August 17, 2009
    The comment has been removed

  • Anonymous
    August 17, 2009
    commongenius: ha-ha, welcome to the club. Being cynical about the state of the programming profession today is my permanent state. One discovery I made is that our profession nowadays is all about human nature, not computers. In the end, computers and software fade away in importance and are just an invisible medium that connects humans. When I look at certain code, I clearly see a human who wrote it back then and it is this human and their nature at its purest that I connect to by means of looking at the produced code. I won't be surprised if we'll require a degree in psychology to become a computer scientist in the near future ;) Surprisingly, computer science is about humans, not computers.

  • Anonymous
    August 17, 2009
    The classic COM factory method :). Thanks Kirill for posting this. By the way you know that CoClass can be looked up in the registry if it is not specified in the attributes (via interface Guid) giving you more powerful ways to consume COM.