new 一个接口?

简介:

如果有人问你,C# 中可以new 一个接口吗?,你会怎么回答?

 

假设ITestInterface 是一个接口,那么这样的代码是否有问题?

ITestInterface testInterface = new ITestInterface();

 

很多书上都会说,当然有问题,接口不能用new ,然后你就认为上面这句语句肯定通不过编译器的编译了。

可是凡事无绝对,C# 竟然允许你这么写,当然你需要加点”料”才行。

 

VS2005 中新建控制台程序CA2005.添加 Microsoft.Office.Interop.Excel 引用

image

image

Program 的Main函数只有一句话:

image

注意,可以通过编译,看下Application的定义:

image

很明显Application 是个interface,

这里我要扯一下,经常看到有人说string 是类还是结构什么的,看下string 的定义:

image

 String 是用class 来修饰的,所以string 100% 是类。

还是扯回来吧,Application 是个接口,但是我们却可以用new  .为什么 

先看下反编译后的代码吧:

image

 

可以看到虽然我们写的是new Application,但是编译器为我们生成的却是new ApplicationClass();

难道Application 有什么特别的地方?

 

仔细的同学一眼就看出了Application是被这两个特性修饰的:

[CoClass(typeof(ApplicationClass))]

[Guid("000208D5-0000-0000-C000-000000000046")]

 

关于CoClass的解释可以看msdn

image

 

有些人不喜欢看msdn,而喜欢看博客的一个原因就是msdn太不直白了。

我个人的理解是CoClass 就好像concrete Class(具体类)

这个特性指示编译器在编译Application的时候,使用ApplicationClass 来实现。

 

回到上面的最初的问题上:

 

如何让这段代码通过编译:

ITestInterface testInterface = new ITestInterface();

 

通过上面的分析,我们很容易将这个特性来修饰我们的自己的接口:

 

namespace CA2005

{

    [CoClass(typeof(TestClass))]

    [Guid("6C8BF7FE-1F6B-437E-BCC8-6D2FF04E66B3")]

    public interface ITestInterface

    {

        void DoSomething();

    }

 

    [Guid("68C7CB18-0DEE-4689-845D-741525281C76")]

    public class TestClass : ITestInterface

    {

        public void DoSomething()

        {

            Console.WriteLine("TestClass:DoSomething");

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            Microsoft.Office.Interop.Excel.Application excelApplication =

                new Microsoft.Office.Interop.Excel.Application();

 

            ITestInterface testInterface = new ITestInterface();

            testInterface.DoSomething();

 

        }

    }

}

 

编译,结果如下:

image

接口被标记了CoClassAttribute,而不是ComImportAttribute.

image

原来想要new 一个接口使用的是编译器对COM的优化和支持。

很明显上面的Application是一个COM对象,所以可以new Application

 

ITestApplication中添加ComImportAttribute 特性:

clip_image002

再次运行,结果如下:

image

查看下反编译的代码:

image

之所以我对VS2005 用红色字体,是因为如果你用VS2010 创建的程序,那么你会看到不一样的反编译结果:

 

public static void Main()

{

      Application application1 = (ApplicationActivator.CreateInstance(Type.GetTypeFromCLSID(new Guid("00024500-0000-0000-C000-000000000046")));

      ITestInterface interface1 = new TestClass();

      interface1.DoSomething();

      Console.ReadLine();

}

 

这里的Type.GetTypeFromCLSID 中的guidApplicationClassGuid,也就是CoClassTypeGuid

[ComSourceInterfaces("Microsoft.Office.Interop.Excel.AppEvents")]

    [Guid("00024500-0000-0000-C000-000000000046")]

    [TypeLibType(2)]

    [ClassInterface(0)]

    public class ApplicationClass : _ApplicationApplicationAppEvents_Event

{

}

这点一定要注意。

 

楼下有些同学说这有什么意义,下面是我的项目实例,也是这个问题才让我研究了这个问题:

在项目中使用了一种C3读卡器,这种读卡器提供了读卡接口(C3ReadCard),但是开发环境是2005,所以不能够C3ReadCard c3=new C3ReadCard();

这点很奇怪,Excel的可以new,但是C3ReadCard却不可以new,但是通过反射去调用实现类就可以使用C3ReadCard的接口。

 

这个问题的意义在于你明白编译器如何去处理new一个接口所生成的代码,也许还有其他的用处,等待你的发现。






本文转自LoveJenny博客园博客,原文链接:http://www.cnblogs.com/LoveJenny/archive/2011/12/15/2288313.html,如需转载请自行联系原作者

目录
相关文章
|
监控 Oracle Java
JVM工作原理与实战(一):初识JVM
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。同时,JVM还具备动态优化功能,可以根据实际运行情况进行调整和优化。本文主要介绍了JVM的概念、JVM的三大核心功能、常见的JVM虚拟机等内容。
759 4
|
存储 开发者
钉钉企业内部应用与第三方企业应用的主要区别
钉钉企业内部应用与第三方企业应用的主要区别
639 1
|
缓存 安全 Java
Eureka配置文件详解(上)
Eureka配置文件详解
1037 0
|
存储 Java 程序员
强制类型转换运算符的深入解析
在编程中,类型转换是一个常见的操作,它允许我们将一个数据类型转换为另一个数据类型。在某些情况下,编译器可以自动执行这种转换,称为隐式类型转换。但在其他情况下,需要程序员显式地指定转换,这就是所谓的强制类型转换。
123 0
|
JavaScript 前端开发
Form表单利用Jquery Validate验证以及ajax提交
Form表单利用Jquery Validate验证以及ajax提交
216 0
|
存储 云计算 虚拟化
什么是IaaS,PaaS和SaaS及其区别
云计算的三种服务模式:IaaS,PaaS和SaaS Infrastructure(基础设施)-as-a-Service,Platform(平台)-as-a-Service,Software(软件)-as-a-Service。
14261 0
|
Linux Perl Windows
Linux基础:常用命令之grep命令详解
如果你是一个新手,请从头阅读这篇文章,如果你只是忘记了grep命令的一些常用选项,请直接查看文章尾部的总结部分即可。 先说说grep命令能做什么?我们可以使用grep命令在文本中查找指定的字符串,就像你在windows中打开txt文件,使用快捷键“Ctrl+F”在文本中查找某个字符串一样,说白了,可以把grep理解成字符串查找工具。
1509 0
|
7天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!