Csharp/C#教程:基于C# 中可以new一个接口?的问题分析分享

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

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

ITestInterfacetestInterface=newITestInterface();

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

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

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

基于C# 中可以new一个接口?的问题分析

基于C# 中可以new一个接口?的问题分析

Program的Main函数只有一句话:

基于C# 中可以new一个接口?的问题分析

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

基于C# 中可以new一个接口?的问题分析

很明显Application是个interface,

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

基于C# 中可以new一个接口?的问题分析

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

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

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

基于C# 中可以new一个接口?的问题分析 

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

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

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

[CoClass(typeof(ApplicationClass))]

[Guid(“000208D5-0000-0000-C000-000000000046”)]

关于CoClass的解释可以看msdn:

基于C# 中可以new一个接口?的问题分析 

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

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

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

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

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

ITestInterfacetestInterface=newITestInterface();

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

namespaceCA2005

{

   [CoClass(typeof(TestClass))]

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

   publicinterfaceITestInterface

   {

       voidDoSomething();

   }

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

   publicclassTestClass:ITestInterface

   {

       publicvoidDoSomething()

       {

           Console.WriteLine(“TestClass:DoSomething”);

       }

   }

   classProgram

   {

       staticvoidMain(string[]args)

       {

           Microsoft.Office.Interop.Excel.ApplicationexcelApplication=

               newMicrosoft.Office.Interop.Excel.Application();

           ITestInterfacetestInterface=newITestInterface();

           testInterface.DoSomething();

       }

   }

}

编译,结果如下:

基于C# 中可以new一个接口?的问题分析

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

基于C# 中可以new一个接口?的问题分析

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

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

 

在ITestApplication中添加ComImportAttribute特性:

基于C# 中可以new一个接口?的问题分析

再次运行,结果如下:

基于C# 中可以new一个接口?的问题分析

查看下反编译的代码:

基于C# 中可以new一个接口?的问题分析

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

publicstaticvoidMain()

{

     Applicationapplication1=(Application)Activator.CreateInstance(Type.GetTypeFromCLSID(newGuid(“00024500-0000-0000-C000-000000000046”)));

     ITestInterfaceinterface1=newTestClass();

     interface1.DoSomething();

     Console.ReadLine();

}

这里的Type.GetTypeFromCLSID中的guid是ApplicationClass的Guid,也就是CoClass中Type的Guid:

[ComSourceInterfaces(“Microsoft.Office.Interop.Excel.AppEvents”)]

   [Guid(“00024500-0000-0000-C000-000000000046”)]

   [TypeLibType(2)]

   [ClassInterface(0)]

   publicclassApplicationClass:_Application,Application,AppEvents_Event

{

}

这点一定要注意。

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

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

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

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

上述就是C#学习教程:基于C# 中可以new一个接口?的问题分析分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)! 您可能感兴趣的文章:C#中new的几种用法详解详解C#用new和override来实现抽象类的重写区别深入理解C#中new、override、virtual关键字的区别C#基础知识之new关键字介绍C#中Override关键字和New关键字的用法详解C#中new和override的区别个人

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/904683.html

(0)
上一篇 2021年10月22日
下一篇 2021年10月22日

精彩推荐