基于C# 中可以new一個(gè)接口?的問(wèn)題分析
如果有人問(wèn)你,C# 中可以new 一個(gè)接口嗎?,你會(huì)怎么回答?
假設(shè)ITestInterface 是一個(gè)接口,那么這樣的代碼是否有問(wèn)題?
ITestInterface testInterface = new ITestInterface();
很多書(shū)上都會(huì)說(shuō),當(dāng)然有問(wèn)題,接口不能用new ,然后你就認(rèn)為上面這句語(yǔ)句肯定通不過(guò)編譯器的編譯了。
可是凡事無(wú)絕對(duì),C# 竟然允許你這么寫(xiě),當(dāng)然你需要加點(diǎn)”料”才行。
在VS2005 中新建控制臺(tái)程序CA2005.添加 Microsoft.Office.Interop.Excel 引用
Program 的Main函數(shù)只有一句話:
注意,可以通過(guò)編譯,看下Application的定義:
很明顯Application 是個(gè)interface,
這里我要扯一下,經(jīng)??吹接腥苏f(shuō)string 是類還是結(jié)構(gòu)什么的,看下string 的定義:
String 是用class 來(lái)修飾的,所以string 100% 是類。
還是扯回來(lái)吧,Application 是個(gè)接口,但是我們卻可以用new .為什么 ?
先看下反編譯后的代碼吧:
可以看到雖然我們寫(xiě)的是new Application,但是編譯器為我們生成的卻是new ApplicationClass();
難道Application 有什么特別的地方?
仔細(xì)的同學(xué)一眼就看出了Application是被這兩個(gè)特性修飾的:
[CoClass(typeof(ApplicationClass))]
[Guid("000208D5-0000-0000-C000-000000000046")]
關(guān)于CoClass的解釋可以看msdn:
有些人不喜歡看msdn,而喜歡看博客的一個(gè)原因就是msdn太不直白了。
我個(gè)人的理解是CoClass 就好像concrete Class(具體類)。
這個(gè)特性指示編譯器在編譯Application的時(shí)候,使用ApplicationClass 來(lái)實(shí)現(xiàn)。
回到上面的最初的問(wèn)題上:
如何讓這段代碼通過(guò)編譯:
ITestInterface testInterface = new ITestInterface();
通過(guò)上面的分析,我們很容易將這個(gè)特性來(lái)修飾我們的自己的接口:
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();
}
}
}
編譯,結(jié)果如下:
接口被標(biāo)記了CoClassAttribute,而不是ComImportAttribute.
原來(lái)想要new 一個(gè)接口使用的是編譯器對(duì)COM的優(yōu)化和支持。
很明顯上面的Application是一個(gè)COM對(duì)象,所以可以new Application
在ITestApplication中添加ComImportAttribute 特性:
再次運(yùn)行,結(jié)果如下:
查看下反編譯的代碼:
之所以我對(duì)VS2005 用紅色字體,是因?yàn)槿绻阌?/SPAN>VS2010 創(chuàng)建的程序,那么你會(huì)看到不一樣的反編譯結(jié)果:
public static void Main()
{
Application application1 = (Application) Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("00024500-0000-0000-C000-000000000046")));
ITestInterface interface1 = new TestClass();
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)]
public class ApplicationClass : _Application, Application, AppEvents_Event
{
}
這點(diǎn)一定要注意。
樓下有些同學(xué)說(shuō)這有什么意義,下面是我的項(xiàng)目實(shí)例,也是這個(gè)問(wèn)題才讓我研究了這個(gè)問(wèn)題:
在項(xiàng)目中使用了一種C3讀卡器,這種讀卡器提供了讀卡接口(C3ReadCard),但是開(kāi)發(fā)環(huán)境是2005,所以不能夠C3ReadCard c3=new C3ReadCard();
這點(diǎn)很奇怪,Excel的可以new,但是C3ReadCard卻不可以new,但是通過(guò)反射去調(diào)用實(shí)現(xiàn)類就可以使用C3ReadCard的接口。
這個(gè)問(wèn)題的意義在于你明白編譯器如何去處理new一個(gè)接口所生成的代碼,也許還有其他的用處,等待你的發(fā)現(xiàn)。
- C# ?的使用小結(jié)
- C#中?、?.、??、??=運(yùn)算符的用法
- C#中單問(wèn)號(hào)(?)和雙問(wèn)號(hào)(??)的用法整理
- C# 運(yùn)算符 ?、??、?: 各種問(wèn)號(hào)的用法和說(shuō)明
- C#中Try-Catch語(yǔ)句真的影響程序性能嗎?
- C#中的問(wèn)號(hào)(?號(hào))用法小結(jié)
- C# null 合并運(yùn)算符??(雙問(wèn)號(hào))使用示例
- 探討c#中的unchecked是什么意思,起什么作用?
- c# 空合并運(yùn)算符“??”的使用詳解
- C# 中的??操作符淺談
- java與c#的區(qū)別、兩者有什么不同?
- c#中?的六種用途
相關(guān)文章
C#實(shí)現(xiàn)獲取不同對(duì)象中名稱相同屬性的方法
這篇文章主要介紹了C#實(shí)現(xiàn)獲取不同對(duì)象中名稱相同屬性的方法,涉及C#操作類與對(duì)象屬性的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09百度人臉識(shí)別之人臉識(shí)別FaceIdentify(簽到考勤)
這篇文章主要為大家詳細(xì)介紹了百度人臉識(shí)別之人臉識(shí)別FaceIdentify,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08C#自定義序列化ISerializable的實(shí)現(xiàn)方法
這篇文章主要介紹了C#自定義序列化ISerializable的實(shí)現(xiàn)方法,涉及C#序列化的操作技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04C#讀取數(shù)據(jù)庫(kù)返回泛型集合詳解(DataSetToList)
本篇文章主要是對(duì)C#讀取數(shù)據(jù)庫(kù)返回泛型集合(DataSetToList)進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01